From 35e7dbbf4e0839233f6a8f3e29eab46cc0c50133 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Sun, 17 Jun 2012 19:13:03 +0000 Subject: [PATCH] better handle -e 'command' if there is a shell expression. If command contains spaces, $ or other known shell commands, it's spawned with a "sh -c $COMMAND" instead. this allows us to start terminology to "watch ps" or things like that. Also changed the return code on failure to 127, similar to system(3). NOTE: should we reset some signals? Remember that ecore traps most of them. SVN revision: 72313 --- src/bin/termpty.c | 56 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/src/bin/termpty.c b/src/bin/termpty.c index 3dbafb3b..83b0a4fd 100644 --- a/src/bin/termpty.c +++ b/src/bin/termpty.c @@ -1411,9 +1411,47 @@ termpty_new(const char *cmd, int w, int h, int backscroll) ty->pid = fork(); if (!ty->pid) { - char **args; + const char *shell = NULL; + const char *args[4] = {NULL, NULL, NULL, NULL}; + Eina_Bool needs_shell; int i; + needs_shell = ((!cmd) || + (strpbrk(cmd, " |&;<>()$`\\\"'*?#") != NULL)); + DBG("cmd='%s' needs_shell=%u", cmd ? cmd : "", needs_shell); + + if (needs_shell) + { + shell = getenv("SHELL"); + if (!shell) + { + uid_t uid = getuid(); + struct passwd *pw = getpwuid(uid); + if (pw) shell = pw->pw_shell; + } + if (!shell) + { + WRN("Could not find shell, fallback to /bin/sh"); + shell = "/bin/sh"; + } + } + + if (!needs_shell) + args[0] = cmd; + else + { + args[0] = shell; + if (cmd) + { + args[1] = "-c"; + args[2] = cmd; + } + } + +#define NC(x) (args[x] != NULL ? args[x] : "") + DBG("exec %s %s %s %s", NC(0), NC(1), NC(2), NC(3)); +#undef NC + for (i = 0; i < 100; i++) { if (i != ty->slavefd) close(i); @@ -1427,22 +1465,12 @@ termpty_new(const char *cmd, int w, int h, int backscroll) if (ioctl(ty->fd, TIOCSCTTY, NULL) < 0) exit(1); - if (!cmd) cmd = getenv("SHELL"); - if (!cmd) - { - uid_t uid = getuid(); - struct passwd *pw = getpwuid(uid); - if (pw) cmd = pw->pw_shell; - } - if (!cmd) cmd = "/bin/sh"; + /* TODO: should we reset signals here? */ - args = malloc(2 * sizeof(char *)); - args[0] = (char *)cmd; - args[1] = NULL; // pretend to be xterm putenv("TERM=xterm"); - execvp(args[0], args); - exit(1); + execvp(args[0], (char *const *)args); + exit(127); /* same as system() for failed commands */ } ty->hand_fd = ecore_main_fd_handler_add(ty->fd, ECORE_FD_READ, _cb_fd_read, ty,