]> git.saurik.com Git - apple/shell_cmds.git/blobdiff - apply/apply.c
shell_cmds-198.tar.gz
[apple/shell_cmds.git] / apply / apply.c
index 80379a03e70cb688ae8c856bb0c2debdc12090db..cf4e9c10f97bfd4ffe044812413b11233071e3b5 100644 (file)
@@ -1,5 +1,3 @@
-/*     $NetBSD: apply.c,v 1.6 1997/12/31 05:53:45 thorpej Exp $        */
-
 /*-
  * Copyright (c) 1994
  *     The Regents of the University of California.  All rights reserved.
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-#ifndef lint
 #if 0
+#ifndef lint
 static char sccsid[] = "@(#)apply.c    8.4 (Berkeley) 4/4/94";
-#else
-__RCSID("$NetBSD: apply.c,v 1.6 1997/12/31 05:53:45 thorpej Exp $");
 #endif
-#endif /* not lint */
+#endif
 
+#include <sys/cdefs.h>
+__RCSID("$FreeBSD: src/usr.bin/apply/apply.c,v 1.22 2002/07/14 18:22:12 alfred Exp $");
+
+#include <sys/types.h>
 #include <sys/wait.h>
 
 #include <ctype.h>
@@ -56,17 +55,16 @@ __RCSID("$NetBSD: apply.c,v 1.6 1997/12/31 05:53:45 thorpej Exp $");
 #include <string.h>
 #include <unistd.h>
 
-int    main __P((int, char **));
-void   usage __P((void));
-int    system __P((const char *));
+#define EXEC   "exec "
+
+static int     exec_shell(const char *, char *, char *);
+static void    usage(void);
 
 int
-main(argc, argv)
-       int argc;
-       char *argv[];
-{
-       int ch, clen, debug, i, l, magic, n, nargs, rval;
-       char *c, *cmd, *p, *q;
+main(int argc, char *argv[]) {
+       int ch, debug, i, magic, n, nargs, offset, rval;
+       size_t clen, cmdsize, l;
+       char *c, *cmd, *name, *p, *q, *shell, *slashp, *tmpshell;
 
        debug = 0;
        magic = '%';            /* Default magic char is `%'. */
@@ -76,7 +74,7 @@ main(argc, argv)
                case 'a':
                        if (optarg[1] != '\0')
                                errx(1,
-                                   "illegal magic character specification.");
+                                   "illegal magic character specification");
                        magic = optarg[0];
                        break;
                case 'd':
@@ -86,7 +84,7 @@ main(argc, argv)
                case '5': case '6': case '7': case '8': case '9':
                        if (nargs != -1)
                                errx(1,
-                                   "only one -# argument may be specified.");
+                                   "only one -# argument may be specified");
                        nargs = optopt - '0';
                        break;
                default:
@@ -110,25 +108,52 @@ main(argc, argv)
                                n = p[0] - '0';
                }
 
+       /*
+        * Figure out the shell and name arguments to pass to execl()
+        * in exec_shell().  Always malloc() shell and just set name
+        * to point at the last part of shell if there are any backslashes,
+        * otherwise just set it to point at the space malloc()'d.  If
+        * SHELL environment variable exists, replace contents of
+        * shell with it.
+        */
+       shell = name = NULL;
+       tmpshell = getenv("SHELL");
+       shell = (tmpshell != NULL) ? strdup(tmpshell) : strdup(_PATH_BSHELL);
+       if (shell == NULL)
+               err(1, "strdup() failed");
+       slashp = strrchr(shell, '/');
+       name = (slashp != NULL) ? slashp + 1 : shell;
+
        /*
         * If there were any %digit references, then use those, otherwise
         * build a new command string with sufficient %digit references at
         * the end to consume (nargs) arguments each time round the loop.
-        * Allocate enough space to hold the maximum command.
+        * Allocate enough space to hold the maximum command.  Save the
+        * size to pass to snprintf().
         */
-       if ((cmd = malloc(sizeof("exec ") - 1 +
-           strlen(argv[0]) + 9 * (sizeof(" %1") - 1) + 1)) == NULL)
-               err(1, "malloc");
-               
+       cmdsize = sizeof(EXEC) - 1 + strlen(argv[0])
+           + 9 * (sizeof(" %1") - 1) + 1;
+       if ((cmd = malloc(cmdsize)) == NULL)
+               err(1, NULL);
+
        if (n == 0) {
                /* If nargs not set, default to a single argument. */
                if (nargs == -1)
                        nargs = 1;
 
                p = cmd;
-               p += sprintf(cmd, "exec %s", argv[0]);
-               for (i = 1; i <= nargs; i++)
-                       p += sprintf(p, " %c%d", magic, i);
+               offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
+               if ((size_t)offset >= cmdsize)
+                       err(1, "snprintf() failed");
+               p += offset;
+               cmdsize -= offset;
+               for (i = 1; i <= nargs; i++) {
+                       offset = snprintf(p, cmdsize, " %c%d", magic, i);
+                       if ((size_t)offset >= cmdsize)
+                               err(1, "snprintf() failed");
+                       p += offset;
+                       cmdsize -= offset;
+               }
 
                /*
                 * If nargs set to the special value 0, eat a single
@@ -137,7 +162,9 @@ main(argc, argv)
                if (nargs == 0)
                        nargs = 1;
        } else {
-               (void)sprintf(cmd, "exec %s", argv[0]);
+               offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
+               if ((size_t)offset >= cmdsize)
+                       err(1, "snprintf() failed");
                nargs = n;
        }
 
@@ -147,7 +174,7 @@ main(argc, argv)
         * for the normal case.
         */
        if ((c = malloc(clen = 1024)) == NULL)
-               err(1, "malloc");
+               err(1, NULL);
 
        /*
         * (argc) and (argv) are still offset by one to make it simpler to
@@ -160,15 +187,20 @@ main(argc, argv)
                 * there's enough space to build it.
                 */
                for (l = strlen(cmd), i = 0; i < nargs; i++)
-                       l += strlen(argv[i]);
+                       l += strlen(argv[i+1]);
                if (l > clen && (c = realloc(c, clen = l)) == NULL)
-                       err(1, "malloc");
+                       err(1, NULL);
 
                /* Expand command argv references. */
                for (p = cmd, q = c; *p != '\0'; ++p)
-                       if (p[0] == magic && isdigit(p[1]) && p[1] != '0')
-                               q += sprintf(q, "%s", argv[(++p)[0] - '0']);
-                       else
+                       if (p[0] == magic && isdigit(p[1]) && p[1] != '0') {
+                               offset = snprintf(q, l, "%s",
+                                   argv[(++p)[0] - '0']);
+                               if ((size_t)offset >= l)
+                                       err(1, "snprintf() failed");
+                               q += offset;
+                               l -= offset;
+                       } else
                                *q++ = *p;
 
                /* Terminate the command string. */
@@ -178,39 +210,31 @@ main(argc, argv)
                if (debug)
                        (void)printf("%s\n", c);
                else
-                       if (system(c))
+                       if (exec_shell(c, shell, name))
                                rval = 1;
        }
 
        if (argc != 1)
                errx(1, "expecting additional argument%s after \"%s\"",
-                   (nargs - argc) ? "s" : "", argv[argc - 1]);
+           (nargs - argc) ? "s" : "", argv[argc - 1]);
+       free(cmd);
+       free(c);
+       free(shell);
        exit(rval);
 }
 
 /*
- * system --
- *     Private version of system(3).  Use the user's SHELL environment
- *     variable as the shell to execute.
+ * exec_shell --
+ *     Execute a shell command using passed use_shell and use_name
+ *     arguments.
  */
-int
-system(command)
-       const char *command;
+static int
+exec_shell(const char *command, char *use_shell, char *use_name)
 {
-       static char *name, *shell;
-       union wait pstat;
        pid_t pid;
-       int omask;
+       int omask, pstat;
        sig_t intsave, quitsave;
 
-       if (shell == NULL) {
-               if ((shell = getenv("SHELL")) == NULL)
-                       shell = _PATH_BSHELL;
-               if ((name = strrchr(shell, '/')) == NULL)
-                       name = shell;
-               else
-                       ++name;
-       }
        if (!command)           /* just checking... */
                return(1);
 
@@ -220,24 +244,24 @@ system(command)
                err(1, "vfork");
        case 0:                         /* child */
                (void)sigsetmask(omask);
-               execl(shell, name, "-c", command, NULL);
-               warn("%s", shell);
+               execl(use_shell, use_name, "-c", command, (char *)NULL);
+               warn("%s", use_shell);
                _exit(1);
        }
        intsave = signal(SIGINT, SIG_IGN);
        quitsave = signal(SIGQUIT, SIG_IGN);
-       pid = waitpid(pid, (int *)&pstat, 0);
+       pid = waitpid(pid, &pstat, 0);
        (void)sigsetmask(omask);
        (void)signal(SIGINT, intsave);
        (void)signal(SIGQUIT, quitsave);
-       return(pid == -1 ? -1 : pstat.w_status);
+       return(pid == -1 ? -1 : pstat);
 }
 
 void
-usage()
+usage(void)
 {
 
        (void)fprintf(stderr,
-           "usage: apply [-a magic] [-0123456789] command arguments ...\n");
+       "usage: apply [-a magic] [-d] [-0123456789] command arguments ...\n");
        exit(1);
 }