From 5849a0588e7b12003f8b9afcfcdc31f46c6b2329 Mon Sep 17 00:00:00 2001 From: TingPing Date: Fri, 25 Apr 2014 13:41:38 -0400 Subject: [PATCH] Use glib to parse and launch commands for util_exec Fixes #958 --- src/common/hexchat.c | 35 --------- src/common/hexchatc.h | 1 - src/common/outbound.c | 4 +- src/common/util.c | 165 +----------------------------------------- src/common/util.h | 4 +- src/fe-gtk/menu.c | 23 +++--- 6 files changed, 19 insertions(+), 213 deletions(-) diff --git a/src/common/hexchat.c b/src/common/hexchat.c index 8729df33..3afe5f75 100644 --- a/src/common/hexchat.c +++ b/src/common/hexchat.c @@ -991,47 +991,12 @@ hexchat_exit (void) fe_exit (); } -#ifndef WIN32 - -static int -child_handler (gpointer userdata) -{ - int pid = GPOINTER_TO_INT (userdata); - - if (waitpid (pid, 0, WNOHANG) == pid) - return 0; /* remove timeout handler */ - return 1; /* keep the timeout handler */ -} - -#endif - void hexchat_exec (const char *cmd) { -#ifdef WIN32 util_exec (cmd); -#else - int pid = util_exec (cmd); - if (pid != -1) - /* zombie avoiding system. Don't ask! it has to be like this to work - with zvt (which overrides the default handler) */ - fe_timeout_add (1000, child_handler, GINT_TO_POINTER (pid)); -#endif } -void -hexchat_execv (char * const argv[]) -{ -#ifdef WIN32 - util_execv (argv); -#else - int pid = util_execv (argv); - if (pid != -1) - /* zombie avoiding system. Don't ask! it has to be like this to work - with zvt (which overrides the default handler) */ - fe_timeout_add (1000, child_handler, GINT_TO_POINTER (pid)); -#endif -} static void set_locale (void) diff --git a/src/common/hexchatc.h b/src/common/hexchatc.h index a999dcf2..9d603870 100644 --- a/src/common/hexchatc.h +++ b/src/common/hexchatc.h @@ -57,6 +57,5 @@ void session_free (session *killsess); void lag_check (void); void hexchat_exit (void); void hexchat_exec (const char *cmd); -void hexchat_execv (char * const argv[]); #endif diff --git a/src/common/outbound.c b/src/common/outbound.c index 5dd0d05f..53dd742d 100644 --- a/src/common/outbound.c +++ b/src/common/outbound.c @@ -1841,8 +1841,10 @@ cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[]) char **argv; int argc; - my_poptParseArgvString (cmd, &argc, &argv); + g_shell_parse_argv (cmd, &argc, &argv, NULL); execvp (argv[0], argv); + + g_strfreev (argv); } /* not reached unless error */ /*printf("exec error\n");*/ diff --git a/src/common/util.c b/src/common/util.c index 69ddaff4..2dc0034b 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1298,171 +1298,10 @@ country_search (char *pattern, void *ud, void (*print)(void *, char *, ...)) } } -/* I think gnome1.0.x isn't necessarily linked against popt, ah well! */ -/* !!! For now use this inlined function, or it would break fe-text building */ -/* .... will find a better solution later. */ -/*#ifndef USE_GNOME*/ - -/* this is taken from gnome-libs 1.2.4 */ -#define POPT_ARGV_ARRAY_GROW_DELTA 5 - -int my_poptParseArgvString(const char * s, int * argcPtr, char *** argvPtr) { - char * buf, * bufStart, * dst; - const char * src; - char quote = '\0'; - int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; - char ** argv = malloc(sizeof(*argv) * argvAlloced); - const char ** argv2; - int argc = 0; - int i, buflen; - - buflen = strlen(s) + 1; -/* bufStart = buf = alloca(buflen);*/ - bufStart = buf = malloc (buflen); - memset(buf, '\0', buflen); - - src = s; - argv[argc] = buf; - - while (*src) { - if (quote == *src) { - quote = '\0'; - } else if (quote) { - if (*src == '\\') { - src++; - if (!*src) { - free(argv); - free(bufStart); - return 1; - } - if (*src != quote) *buf++ = '\\'; - } - *buf++ = *src; - /*} else if (isspace((unsigned char) *src)) {*/ - } else if (*src == ' ') { - if (*argv[argc]) { - buf++, argc++; - if (argc == argvAlloced) { - char **temp; - argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; - temp = realloc(argv, sizeof(*argv) * argvAlloced); - if (temp) - argv = temp; - else - { - free(argv); - free(bufStart); - return 1; - } - } - argv[argc] = buf; - } - } else switch (*src) { - case '"': - case '\'': - quote = *src; - break; - case '\\': - src++; - if (!*src) { - free(argv); - free(bufStart); - return 1; - } - /* fallthrough */ - default: - *buf++ = *src; - } - - src++; - } - - if (strlen(argv[argc])) { - argc++, buf++; - } - - dst = malloc((argc + 1) * sizeof(*argv) + (buf - bufStart)); - argv2 = (void *) dst; - dst += (argc + 1) * sizeof(*argv); - memcpy((void *)argv2, argv, argc * sizeof(*argv)); - argv2[argc] = NULL; - memcpy(dst, bufStart, buf - bufStart); - - for (i = 0; i < argc; i++) { - argv2[i] = dst + (argv[i] - bufStart); - } - - free(argv); - - *argvPtr = (char **)argv2; /* XXX don't change the API */ - *argcPtr = argc; - - free (bufStart); - - return 0; -} - -int +void util_exec (const char *cmd) { - char **argv; - int argc; -#ifndef WIN32 - int pid; - int fd; -#endif - - if (my_poptParseArgvString (cmd, &argc, &argv) != 0) - return -1; - -#ifndef WIN32 - pid = fork (); - if (pid == -1) - { - free (argv); - return -1; - } - if (pid == 0) - { - /* Now close all open file descriptors except stdin, stdout and stderr */ - for (fd = 3; fd < 1024; fd++) close(fd); - execvp (argv[0], argv); - _exit (0); - } else - { - free (argv); - return pid; - } -#else - spawnvp (_P_DETACH, argv[0], argv); - free (argv); - return 0; -#endif -} - -int -util_execv (char * const argv[]) -{ -#ifndef WIN32 - int pid, fd; - - pid = fork (); - if (pid == -1) - return -1; - if (pid == 0) - { - /* Now close all open file descriptors except stdin, stdout and stderr */ - for (fd = 3; fd < 1024; fd++) close(fd); - execv (argv[0], argv); - _exit (0); - } else - { - return pid; - } -#else - spawnv (_P_DETACH, argv[0], argv); - return 0; -#endif + g_spawn_command_line_async (cmd, NULL); } unsigned long diff --git a/src/common/util.h b/src/common/util.h index f2fe2ecb..5231e56d 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -37,7 +37,6 @@ extern const unsigned char rfc_tolowertab[]; -int my_poptParseArgvString(const char * s, int * argcPtr, char *** argvPtr); char *expand_homedir (char *file); void path_part (char *file, char *path, int pathlen); int match (const char *mask, const char *string); @@ -50,8 +49,7 @@ char *nocasestrstr (const char *text, const char *tofind); char *country (char *); void country_search (char *pattern, void *ud, void (*print)(void *, char *, ...)); char *get_sys_str (int with_cpu); -int util_exec (const char *cmd); -int util_execv (char * const argv[]); +void util_exec (const char *cmd); #define STRIP_COLOR 1 #define STRIP_ATTRIB 2 #define STRIP_HIDDEN 4 diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c index 39c0ad5a..c37fbc8e 100644 --- a/src/fe-gtk/menu.c +++ b/src/fe-gtk/menu.c @@ -403,8 +403,10 @@ toggle_cb (GtkWidget *item, char *pref_name) static int is_in_path (char *cmd) { - char *prog = strdup (cmd + 1); /* 1st char is "!" */ + char *prog = g_strdup (cmd + 1); /* 1st char is "!" */ char *space, *path, *orig; + char **argv; + int argc; orig = prog; /* save for free()ing */ /* special-case these default entries. */ @@ -413,16 +415,17 @@ is_in_path (char *cmd) /* don't check for gnome-terminal, but the thing it's executing! */ prog += 18; - space = strchr (prog, ' '); /* this isn't 100% but good enuf */ - if (space) - *space = 0; - - path = g_find_program_in_path (prog); - if (path) + if (g_shell_parse_argv (prog, &argc, &argv, NULL)) { - g_free (path); - g_free (orig); - return 1; + path = g_find_program_in_path (argv[0]); + if (path) + { + g_free (path); + g_free (orig); + g_strfreev (argv); + return 1; + } + g_strfreev (argv); } g_free (orig);