Use glib to parse and launch commands for util_exec

Fixes #958
This commit is contained in:
TingPing 2014-04-25 13:41:38 -04:00 committed by TingPing
parent b8c02f71d9
commit 5849a0588e
6 changed files with 19 additions and 213 deletions

View File

@ -991,47 +991,12 @@ hexchat_exit (void)
fe_exit (); 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 void
hexchat_exec (const char *cmd) hexchat_exec (const char *cmd)
{ {
#ifdef WIN32
util_exec (cmd); 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 static void
set_locale (void) set_locale (void)

View File

@ -57,6 +57,5 @@ void session_free (session *killsess);
void lag_check (void); void lag_check (void);
void hexchat_exit (void); void hexchat_exit (void);
void hexchat_exec (const char *cmd); void hexchat_exec (const char *cmd);
void hexchat_execv (char * const argv[]);
#endif #endif

View File

@ -1841,8 +1841,10 @@ cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
char **argv; char **argv;
int argc; int argc;
my_poptParseArgvString (cmd, &argc, &argv); g_shell_parse_argv (cmd, &argc, &argv, NULL);
execvp (argv[0], argv); execvp (argv[0], argv);
g_strfreev (argv);
} }
/* not reached unless error */ /* not reached unless error */
/*printf("exec error\n");*/ /*printf("exec error\n");*/

View File

@ -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! */ void
/* !!! 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
util_exec (const char *cmd) util_exec (const char *cmd)
{ {
char **argv; g_spawn_command_line_async (cmd, NULL);
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
} }
unsigned long unsigned long

View File

@ -37,7 +37,6 @@
extern const unsigned char rfc_tolowertab[]; extern const unsigned char rfc_tolowertab[];
int my_poptParseArgvString(const char * s, int * argcPtr, char *** argvPtr);
char *expand_homedir (char *file); char *expand_homedir (char *file);
void path_part (char *file, char *path, int pathlen); void path_part (char *file, char *path, int pathlen);
int match (const char *mask, const char *string); int match (const char *mask, const char *string);
@ -50,8 +49,7 @@ char *nocasestrstr (const char *text, const char *tofind);
char *country (char *); char *country (char *);
void country_search (char *pattern, void *ud, void (*print)(void *, char *, ...)); void country_search (char *pattern, void *ud, void (*print)(void *, char *, ...));
char *get_sys_str (int with_cpu); char *get_sys_str (int with_cpu);
int util_exec (const char *cmd); void util_exec (const char *cmd);
int util_execv (char * const argv[]);
#define STRIP_COLOR 1 #define STRIP_COLOR 1
#define STRIP_ATTRIB 2 #define STRIP_ATTRIB 2
#define STRIP_HIDDEN 4 #define STRIP_HIDDEN 4

View File

@ -403,8 +403,10 @@ toggle_cb (GtkWidget *item, char *pref_name)
static int static int
is_in_path (char *cmd) 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 *space, *path, *orig;
char **argv;
int argc;
orig = prog; /* save for free()ing */ orig = prog; /* save for free()ing */
/* special-case these default entries. */ /* special-case these default entries. */
@ -413,17 +415,18 @@ is_in_path (char *cmd)
/* don't check for gnome-terminal, but the thing it's executing! */ /* don't check for gnome-terminal, but the thing it's executing! */
prog += 18; prog += 18;
space = strchr (prog, ' '); /* this isn't 100% but good enuf */ if (g_shell_parse_argv (prog, &argc, &argv, NULL))
if (space) {
*space = 0; path = g_find_program_in_path (argv[0]);
path = g_find_program_in_path (prog);
if (path) if (path)
{ {
g_free (path); g_free (path);
g_free (orig); g_free (orig);
g_strfreev (argv);
return 1; return 1;
} }
g_strfreev (argv);
}
g_free (orig); g_free (orig);
return 0; return 0;