allocate memory fast, use the user's SHELL, make -0 work, exit 0
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Tue, 5 Apr 1994 00:17:17 +0000 (16:17 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Tue, 5 Apr 1994 00:17:17 +0000 (16:17 -0800)
if everything worked, minor KNF

SCCS-vsn: usr.bin/apply/apply.c 8.3

usr/src/usr.bin/apply/apply.c

index f4edfce..36b4897 100644 (file)
@@ -9,52 +9,55 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)apply.c    8.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)apply.c    8.3 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
+#include <sys/wait.h>
+
+#include <ctype.h>
 #include <err.h>
 #include <err.h>
+#include <paths.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 void   usage __P((void));
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 void   usage __P((void));
+int    system __P((const char *));
 
 int
 main(argc, argv)
        int argc;
        char *argv[];
 {
 
 int
 main(argc, argv)
        int argc;
        char *argv[];
 {
-       int ch, clen, debug, error, n, nargs;
-       char *c, *cmd, magic, *p;
+       int ch, clen, debug, i, l, magic, n, nargs, rval;
+       char *c, *cmd, *p, *q;
 
        debug = 0;
 
        debug = 0;
-       magic = '%';            /* default magic char is `%' */
-       nargs = 1;              /* default to a single arg */
-
-       while ((ch = getopt(argc, argv, "a:d0123456789")) != EOF) {
+       magic = '%';            /* Default magic char is `%'. */
+       nargs = -1;
+       while ((ch = getopt(argc, argv, "a:d0123456789")) != EOF)
                switch (ch) {
                switch (ch) {
-                       case 'a':
-                               magic = *optarg;
-                               break;
-
-                       case 'd':
-                               debug = 1;
-                               break;
-
-                       case '0': case '1': case '2':
-                       case '3': case '4': case '5':
-                       case '6': case '7': case '8':
-                       case '9':
-                               nargs = optopt - '0';
-                               break;
-
-                       default:
-                               usage();
-                               break;
+               case 'a':
+                       if (optarg[1] != '\0')
+                               errx(1,
+                                   "illegal magic character specification.");
+                       magic = optarg[0];
+                       break;
+               case 'd':
+                       debug = 1;
+                       break;
+               case '0': case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                       if (nargs != -1)
+                               errx(1,
+                                   "only one -# argument may be specified.");
+                       nargs = optopt - '0';
+                       break;
+               default:
+                       usage();
                }
                }
-       }
-
        argc -= optind;
        argv += optind;
 
        argc -= optind;
        argv += optind;
 
@@ -62,136 +65,143 @@ main(argc, argv)
                usage();
 
        /*
                usage();
 
        /*
-        * The command to run is argv[0], and the args are argv[1..]
+        * The command to run is argv[0], and the args are argv[1..].
+        * Look for %digit references in the command, remembering the
+        * largest one.
         */
         */
-       cmd = argv[0];
-
-       /*
-        * Look for %digit references, remembering the
-        * largest value found.
-        */
-       n = 0;
-       for (p = cmd; (p = strchr(p, magic)) != NULL; p++) {
-               p++;
-               switch (*p) {
-               case '1': case '2': case '3':
-               case '4': case '5': case '6':
-               case '7': case '8': case '9':
-                       if ((*p - '0') > n)
-                               n = *p - '0';
-                       break;
+       for (n = 0, p = argv[0]; *p != '\0'; ++p)
+               if (p[0] == magic && isdigit(p[1]) && p[1] != '0') {
+                       ++p;
+                       if (p[0] - '0' > n)
+                               n = p[0] - '0';
                }
                }
-       }
 
        /*
 
        /*
-        * If there were any %digit references, then
-        * simply use those, otherwise build a new command
-        * string with sufficient %digit references at
-        * the end to consume (nargs) arguments each time
-        * round the loop.
+        * 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.
         */
         */
-       c = malloc(sizeof("exec") + strlen(cmd) + 3 * nargs + 1);
-       if (c == NULL)
+       if ((cmd =
+           malloc(sizeof("exec") + strlen(argv[0]) + 3 * nargs + 1)) == NULL)
                err(1, NULL);
                
                err(1, NULL);
                
-       if (n > 0) {
-               (void)sprintf(c, "exec %s", cmd);
-               nargs = n;
-       } else {
-               int i;
+       if (n == 0) {
+               /* If nargs not set, default to a single argument. */
+               if (nargs == -1)
+                       nargs = 1;
 
 
-               p = c;
-               p += sprintf(c, "exec %s", cmd);
+               p = cmd;
+               p += sprintf(cmd, "exec %s", argv[0]);
                for (i = 1; i <= nargs; i++)
                        p += sprintf(p, " %c%d", magic, i);
                for (i = 1; i <= nargs; i++)
                        p += sprintf(p, " %c%d", magic, i);
+
+               /*
+                * If nargs set to the special value 0, eat a single
+                * argument for each command execution.
+                */
+               if (nargs == 0)
+                       nargs = 1;
+       } else {
+               (void)sprintf(cmd, "exec %s", argv[0]);
+               nargs = n;
        }
        }
-       cmd = c;
 
        /*
 
        /*
-        * (argc) and (argv) are still offset by one to make it
-        * simpler to expand %digit references.
-        * At the end of the loop check for (argc) equals 1 means
-        * that all the (argv) has been consumed.
+        * Grab some space in which to build the command.  Allocate
+        * as necessary later, but no reason to build it up slowly
+        * for the normal case.
         */
         */
-       c = 0;
-       clen = 0;
-       error = 0;
-
-       while (argc > nargs) {
-               int i, l;
-               char *c, *q;
+       if ((c = malloc(clen = 1024)) == NULL)
+               err(1, NULL);
 
 
-               /* find tentative value for command length */
-               l = strlen(cmd);
-               for (i = 0; i < nargs; i++)
+       /*
+        * (argc) and (argv) are still offset by one to make it simpler to
+        * expand %digit references.  At the end of the loop check for (argc)
+        * equals 1 means that all the (argv) has been consumed.
+        */
+       for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) {
+               /*
+                * Find a max value for the command length, and ensure
+                * there's enough space to build it.
+                */
+               for (l = strlen(cmd), i = 0; i < nargs; i++)
                        l += strlen(argv[i]);
                        l += strlen(argv[i]);
-
-               /* ensure enough space to build the command */
-               if (l > clen) {
-                       clen = l;
-                       c = realloc(c, clen);
-                       if (c == NULL)
-                               err(1, NULL);
-               }
-
-               /* expand all command references */
-               for (p = cmd, q = c; *p; p++) {
-                       if (*p != magic) {
+               if (l > clen && (c = realloc(c, clen = l)) == NULL)
+                       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
                                *q++ = *p;
                                *q++ = *p;
-                               continue;
-                       }
-                       p++;
-
-                       switch (*p) {
-                       case '1': case '2': case '3':
-                       case '4': case '5': case '6':
-                       case '7': case '8': case '9':
-                               strcpy(q, argv[*p - '0']);
-                               q += strlen(q);
-                               break;
-
-                       default:
-                               *q++ = magic;
-                               *q++ = *p;
-                               break;
-                       }
-               }
 
 
-               /* terminate the command string */
+               /* Terminate the command string. */
                *q = '\0';
 
                *q = '\0';
 
-               /* run the command */
-               if (debug) {
-                       puts(c);
-               } else {
+               /* Run the command. */
+               if (debug)
+                       (void)printf("%s\n", c);
+               else
                        if (system(c))
                        if (system(c))
-                               error = 1;
-               }
-
-               /*
-                * bump the arg vector.  if -0 was on the command
-                * line, then still need to skip one argument.
-                */
-               if (nargs) {
-                       argc -= nargs;
-                       argv += nargs;
-               } else {
-                       --argc;
-                       argv++;
-               }
+                               rval = 1;
        }
 
        if (argc != 1)
        }
 
        if (argc != 1)
-               errx(1, "expecting argument%s after \"%s\"",
-                       (nargs-argc) ? "s" : "", argv[argc-1]);
-       
-       exit(1);
+               errx(1, "expecting additional argument%s after \"%s\"",
+                   (nargs - argc) ? "s" : "", argv[argc - 1]);
+       exit(rval);
+}
+
+/*
+ * system --
+ *     Private version of system(3).  Use the user's SHELL environment
+ *     variable as the shell to execute.
+ */
+int
+system(command)
+       const char *command;
+{
+       static char *name, *shell;
+       union wait pstat;
+       pid_t pid;
+       int omask;
+       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);
+
+       omask = sigblock(sigmask(SIGCHLD));
+       switch(pid = vfork()) {
+       case -1:                        /* error */
+               err(1, "fork");
+       case 0:                         /* child */
+               (void)sigsetmask(omask);
+               execl(shell, name, "-c", command, NULL);
+               err(1, "%s", shell);
+       }
+       intsave = signal(SIGINT, SIG_IGN);
+       quitsave = signal(SIGQUIT, SIG_IGN);
+       pid = waitpid(pid, (int *)&pstat, 0);
+       (void)sigsetmask(omask);
+       (void)signal(SIGINT, intsave);
+       (void)signal(SIGQUIT, quitsave);
+       return(pid == -1 ? -1 : pstat.w_status);
 }
 
 void
 usage()
 {
 
 }
 
 void
 usage()
 {
 
-       (void)fprintf(stderr, "usage: apply [-an] [-0..9] cmd args ...\n");
+       (void)fprintf(stderr,
+           "usage: apply [-a magic] [-0123456789] command arguments ...\n");
        exit(1);
 }
        exit(1);
 }