]> Sergey Matveev's repositories - nnn.git/commitdiff
Fix #179
authorArun Prakash Jana <engineerarun@gmail.com>
Sun, 10 Mar 2019 05:43:12 +0000 (11:13 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sun, 10 Mar 2019 06:32:59 +0000 (12:02 +0530)
src/nnn.c

index ffca34acc8a9384e62dfaec487c26f8566c84e53..90146b6b205573b774a0f8742b0289e12b5800a5 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -186,6 +186,7 @@ disabledbg()
 #define CTX_MAX 4
 #define DOT_FILTER_LEN 7
 #define ASCII_MAX 128
+#define EXEC_ARGS_MAX 8
 
 /* Entry flags */
 #define DIR_OR_LINK_TO_DIR 0x1
@@ -198,6 +199,7 @@ disabledbg()
 #define F_NOTRACE  0x04  /* suppress stdout and strerr (no traces) */
 #define F_SIGINT   0x08  /* restore default SIGINT handler */
 #define F_EDITOR   0x10  /* spawn the editor */
+#define F_MULTI    0x20  /* first arg can be combination of args */
 #define F_NORMAL   0x80  /* spawn child process in non-curses regular CLI mode */
 
 /* CRC8 macros */
@@ -491,7 +493,7 @@ static const char * const envs[] = {
 
 /* Forward declarations */
 static void redraw(char *path);
-static void spawn(const char *file, const char *arg1, const char *arg2, const char *dir, uchar flag);
+static void spawn(char *file, char *arg1, char *arg2, const char *dir, uchar flag);
 static int (*nftw_fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
 
 /* Functions */
@@ -969,23 +971,77 @@ static bool initcurses(void)
        return TRUE;
 }
 
+/* NOTE: There's no NULL check here */
+
+static int parseargs(char *line, char **argv)
+{
+       int count = 0;
+
+       argv[count++] = line;
+
+       while (*line) {
+               if (isblank(*line)) {
+                       *line++ = '\0';
+
+                       if (!*line)
+                               return count;
+
+                       argv[count++] = line;
+                       if (count == EXEC_ARGS_MAX)
+                               return -1;
+               }
+
+               ++line;
+        }
+
+       return count;
+}
+
 /*
  * Spawns a child process. Behaviour can be controlled using flag.
  * Limited to 2 arguments to a program, flag works on bit set.
  */
-static void spawn(const char *file, const char *arg1, const char *arg2, const char *dir, uchar flag)
+static void spawn(char *file, char *arg1, char *arg2, const char *dir, uchar flag)
 {
        pid_t pid;
        int status;
-       const char *tmp;
+       char *argv[EXEC_ARGS_MAX] = {0};
+       char *cmd = NULL;
+
+       if (!file || !file[0])
+               return;
 
        /* Swap args if the first arg is NULL and second isn't */
        if (!arg1 && arg2) {
-               tmp = arg1;
                arg1 = arg2;
-               arg2 = tmp;
+               arg2 = NULL;
+       }
+
+       if (flag & F_MULTI) {
+               size_t len = strlen(file) + 1;
+               cmd = (char *)malloc(len);
+               if (!cmd) {
+                       DPRINTF_S("spawn: malloc()!");
+                       return;
+               }
+
+               xstrlcpy(cmd, file, len);
+               argv[0] = file;
+               status = parseargs(cmd, argv);
+               if (status == -1 || status > (EXEC_ARGS_MAX - 2)) { /* arg1 and last NULL */
+                       free(cmd);
+                       DPRINTF_S("spawn: NULL or too many args");
+                       return;
+               }
+
+               argv[status] = arg1;
+       } else {
+               argv[0] = file;
+               argv[1] = arg1;
+               argv[2] = arg2;
        }
 
+
        if (flag & F_NORMAL)
                exitcurses();
 
@@ -1012,7 +1068,7 @@ static void spawn(const char *file, const char *arg1, const char *arg2, const ch
                if (flag & F_SIGINT)
                        signal(SIGINT, SIG_DFL);
 
-               execlp(file, file, arg1, arg2, NULL);
+               execvp(*argv, argv);
                _exit(1);
        } else {
                if (!(flag & F_NOWAIT))
@@ -1029,50 +1085,9 @@ static void spawn(const char *file, const char *arg1, const char *arg2, const ch
                                initcurses();
                        }
                }
-       }
-}
 
-/*
- * Quotes argument and spawns a shell command
- * Uses g_buf
- */
-static bool quote_run_sh_cmd(const char *cmd, const char *arg, const char *path)
-{
-       const char *ptr;
-       size_t r;
-
-       if (!cmd)
-               return FALSE;
-
-       r = xstrlcpy(g_buf, cmd, CMD_LEN_MAX);
-
-       if (arg) {
-               if (r >= CMD_LEN_MAX - 4) { /* space for at least 4 chars - space'c' */
-                       printmsg(messages[STR_UNSAFE]);
-                       return FALSE;
-               }
-
-               for (ptr = arg; *ptr; ++ptr)
-                       if (*ptr == '\'') {
-                               printmsg(messages[STR_UNSAFE]);
-                               return FALSE;
-                       }
-
-               g_buf[r - 1] = ' ';
-               g_buf[r] = '\'';
-               r += xstrlcpy(g_buf + r + 1, arg, CMD_LEN_MAX - 1 - r);
-               if (r >= CMD_LEN_MAX - 1) {
-                       printmsg(messages[STR_UNSAFE]);
-                       return FALSE;
-               }
-
-               g_buf[r] = '\'';
-               g_buf[r + 1] = '\0';
+               free(cmd);
        }
-
-       DPRINTF_S(g_buf);
-       spawn("sh", "-c", g_buf, path, F_NORMAL | F_EDITOR);
-       return TRUE;
 }
 
 /* Get program name from env var, else return fallback program */
@@ -2318,7 +2333,7 @@ static bool show_mediainfo(const char *fpath, const char *arg)
        return TRUE;
 }
 
-static bool handle_archive(const char *fpath, const char *arg, const char *dir)
+static bool handle_archive(char *fpath, char *arg, const char *dir)
 {
        if (!getutil(utils[ATOOL]))
                return FALSE;
@@ -3008,8 +3023,8 @@ nochange:
                                    get_output(g_buf, CMD_LEN_MAX, "file", FILE_OPTS, newpath, FALSE)
                                    && g_buf[0] == 't' && g_buf[1] == 'e' && g_buf[2] == 'x'
                                    && g_buf[3] == g_buf[0] && g_buf[4] == '/') {
-                                       if (!quote_run_sh_cmd(editor, newpath, path))
-                                               goto nochange;
+                                       spawn(editor, newpath, NULL, path,
+                                             F_NORMAL | F_EDITOR | F_MULTI);
                                        continue;
                                }
 
@@ -3355,8 +3370,8 @@ nochange:
                                r = show_help(path);
                                break;
                        case SEL_RUNEDIT:
-                               if (!quote_run_sh_cmd(editor, dents[cur].name, path))
-                                       goto nochange;
+                               spawn(editor, dents[cur].name, NULL, path,
+                                     F_NORMAL | F_EDITOR |F_MULTI);
                                break;
                        case SEL_RUNPAGE:
                                spawn(pager, pager_arg, dents[cur].name, path, F_NORMAL);
@@ -3371,8 +3386,7 @@ nochange:
                                        goto nochange;
                                }
 
-                               if (!quote_run_sh_cmd(editor, notepath, NULL))
-                                       goto nochange;
+                               spawn(editor, notepath, NULL, path, F_NORMAL | F_EDITOR |F_MULTI);
                                break;
                        }
                        default: /* SEL_LOCK */