wmenu-run.c (2116B)
1 #define _POSIX_C_SOURCE 200809L 2 #include <dirent.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <unistd.h> 7 8 #include "menu.h" 9 #include "wayland.h" 10 #include "xdg-activation-v1-client-protocol.h" 11 12 static void read_items(struct menu *menu) { 13 char *path = strdup(getenv("PATH")); 14 for (char *p = strtok(path, ":"); p != NULL; p = strtok(NULL, ":")) { 15 DIR *dir = opendir(p); 16 if (dir == NULL) { 17 continue; 18 } 19 for (struct dirent *ent = readdir(dir); ent != NULL; ent = readdir(dir)) { 20 if (ent->d_name[0] == '.') { 21 continue; 22 } 23 menu_add_item(menu, strdup(ent->d_name)); 24 } 25 closedir(dir); 26 } 27 menu_sort_and_deduplicate(menu); 28 free(path); 29 } 30 31 struct command { 32 struct menu *menu; 33 char *text; 34 bool exit; 35 }; 36 37 static void activation_token_done(void *data, struct xdg_activation_token_v1 *activation_token, 38 const char *token) { 39 struct command *cmd = data; 40 xdg_activation_token_v1_destroy(activation_token); 41 42 int pid = fork(); 43 if (pid == 0) { 44 setenv("XDG_ACTIVATION_TOKEN", token, true); 45 char *argv[] = {"/bin/sh", "-c", cmd->text, NULL}; 46 execvp(argv[0], (char**)argv); 47 } else { 48 if (cmd->exit) { 49 cmd->menu->exit = true; 50 } 51 } 52 } 53 54 static const struct xdg_activation_token_v1_listener activation_token_listener = { 55 .done = activation_token_done, 56 }; 57 58 static void exec_item(struct menu *menu, char *text, bool exit) { 59 struct command *cmd = calloc(1, sizeof(struct command)); 60 cmd->menu = menu; 61 cmd->text = strdup(text); 62 cmd->exit = exit; 63 64 struct xdg_activation_v1 *activation = context_get_xdg_activation(menu->context); 65 struct xdg_activation_token_v1 *activation_token = xdg_activation_v1_get_activation_token(activation); 66 xdg_activation_token_v1_set_surface(activation_token, context_get_surface(menu->context)); 67 xdg_activation_token_v1_add_listener(activation_token, &activation_token_listener, cmd); 68 xdg_activation_token_v1_commit(activation_token); 69 } 70 71 int main(int argc, char *argv[]) { 72 struct menu *menu = menu_create(exec_item); 73 menu_getopts(menu, argc, argv); 74 read_items(menu); 75 int status = menu_run(menu); 76 menu_destroy(menu); 77 return status; 78 }