implemented exec_command with wordexp(3)

this allows for a less error-prone parsing method
(as wordexp(3) is in libc) and enables for shell-like
word expansion, refer to the man page for more info
about wordexp(3)
xkbcommon
Alessandro Mauri 4 years ago
parent d39281f9a6
commit 05a18e8874
  1. 93
      hkd.c

93
hkd.c

@ -14,6 +14,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <wordexp.h>
#define FILE_NAME_MAX_LENGTH 255 #define FILE_NAME_MAX_LENGTH 255
#define KEY_BUFFER_SIZE 16 #define KEY_BUFFER_SIZE 16
@ -30,7 +31,7 @@
#define green(str) (ANSI_COLOR_GREEN str ANSI_COLOR_RESET) #define green(str) (ANSI_COLOR_GREEN str ANSI_COLOR_RESET)
#define red(str) (ANSI_COLOR_RED str ANSI_COLOR_RESET) #define red(str) (ANSI_COLOR_RED str ANSI_COLOR_RESET)
#define test_bit(yalv, abs_b) ((((char *)abs_b)[yalv/8] & (1<<yalv%8)) > 0) #define test_bit(yalv, abs_b) ((((char *)abs_b)[yalv/8] & (1<<yalv%8)) > 0)
#define die(str) {perror(red(str)); exit(errno);} #define die(str) {fputs(ANSI_COLOR_RED, stderr); perror(str); fputs(ANSI_COLOR_RESET, stderr); exit(errno);}
#define array_size(val) (val ? sizeof(val)/sizeof(val[0]) : 0) #define array_size(val) (val ? sizeof(val)/sizeof(val[0]) : 0)
#define EVENT_SIZE (sizeof(struct inotify_event)) #define EVENT_SIZE (sizeof(struct inotify_event))
@ -187,13 +188,12 @@ const char evdev_root_dir[] = "/dev/input/";
int key_buffer_add (struct key_buffer*, unsigned short); int key_buffer_add (struct key_buffer*, unsigned short);
int key_buffer_remove (struct key_buffer*, unsigned short); int key_buffer_remove (struct key_buffer*, unsigned short);
int key_buffer_compare_random (struct key_buffer *haystack, struct key_buffer *needle); int key_buffer_compare_random (struct key_buffer *, struct key_buffer *);
int key_buffer_compare_ordered (struct key_buffer *haystack, struct key_buffer *needle); int key_buffer_compare_ordered (struct key_buffer *, struct key_buffer *);
void int_handler (int signum); void int_handler (int signum);
void exec_command (char *); void exec_command (char *);
void update_descriptors_list (int **, int *); void update_descriptors_list (int **, int *);
int prepare_epoll (int *, int, int); int prepare_epoll (int *, int, int);
void str_to_argv (char ***, const char *);
// TODO: use getopts() to parse command line options // TODO: use getopts() to parse command line options
int main (void) int main (void)
@ -261,11 +261,11 @@ int main (void)
) { ) {
switch (event.value) { switch (event.value) {
/* Key released */ /* Key released */
case (0): case 0:
key_buffer_remove(&pb, event.code); key_buffer_remove(&pb, event.code);
break; break;
/* Key pressed */ /* Key pressed */
case (1): case 1:
key_buffer_add(&pb, event.code); key_buffer_add(&pb, event.code);
break; break;
} }
@ -281,7 +281,7 @@ int main (void)
putchar('\n'); putchar('\n');
if (key_buffer_compare_ordered(&pb, &comb1)) if (key_buffer_compare_ordered(&pb, &comb1))
exec_command("ufetch"); exec_command("ls -l [a-z]*");
} }
} }
@ -337,31 +337,42 @@ void int_handler (int signum)
dead = 1; dead = 1;
} }
void exec_command (char *path) /* Executes a command from a string */
void exec_command (char *command)
{ {
char **argv = NULL; static wordexp_t result;
str_to_argv(&argv, path);
switch (fork()) { /* Expand the string for the program to run */
switch (wordexp (command, &result, 0)) {
case 0:
break;
case WRDE_NOSPACE:
/* If the error was WRDE_NOSPACE,
* then perhaps part of the result was allocated */
wordfree (&result);
return;
default:
/* Some other error */
fprintf(stderr, "Could not parse, %s is not valid", command);
return;
}
pid_t cpid;
switch (cpid = fork()) {
case -1: case -1:
die("Could not fork"); fprintf(stderr, "Could not create child process: %s", strerror(errno));
wordfree(&result);
break; break;
case 0: case 0:
/* we are the child */ /* This is the child process, execute the command */
if (!argv) { execvp(result.we_wordv[0], result.we_wordv);
printf(red("No command to execute\n")); die("Could not run command");
exit(1); break;
} default:
if(execvp(path, argv) < 0) { while (waitpid(cpid, NULL, WNOHANG) == -1) {}
/* execv only returns if an error occured, so we exit wordfree(&result);
* otherwise we duplicate the process */
fprintf(stderr, red("Could not run %s\n"), path);
exit(-1);
}
/* we shouldn't be here */
break; break;
} }
// TODO: communication between parent and child about process status/errors/etc
} }
void update_descriptors_list (int **fds, int *fd_num) void update_descriptors_list (int **fds, int *fd_num)
@ -471,35 +482,3 @@ int key_buffer_compare_ordered (struct key_buffer *haystack, struct key_buffer *
} }
return 1; return 1;
} }
void str_to_argv (char ***argv, const char *path)
{
char * str = NULL;
if (!(str = malloc(sizeof(path))))
die("malloc in str_to_argv()");
strcpy(str, path);
char *token = NULL;
token = strtok(str, " ");
if (!token) {
if (!(*argv = realloc(*argv, sizeof(char *))))
die("realloc in str_to_argv()");
*argv[0] = malloc(sizeof(str));
strcpy(*argv[0], str);
goto end_return;
} else {
if (!(*argv = realloc(*argv, sizeof(char *))))
die("realloc in str_to_argv()");
*argv[0] = malloc(sizeof(token));
strcpy(*argv[0], token);
}
for (int i = 1; (token = strtok(NULL, " ")); i++) {
if (!(*argv = realloc(*argv, sizeof(char *) * (i + 1))))
die("realloc in str_to_argv()");
*argv[i] = malloc(sizeof(token));
strcpy(*argv[i], token);
}
end_return:
free(str);
return;
}

Loading…
Cancel
Save