summaryrefslogtreecommitdiffstats
path: root/usr.bin/apply
diff options
context:
space:
mode:
authorwill <will@FreeBSD.org>2001-01-05 18:15:17 +0000
committerwill <will@FreeBSD.org>2001-01-05 18:15:17 +0000
commit733a059cc15d1f317ac496d140bfd1dcc325a249 (patch)
tree73e497c1eb8de590e17ea688f66fc1917bb825ae /usr.bin/apply
parent729a83c25cb4d059eb77b954f6990dfb1d3e3dde (diff)
downloadFreeBSD-src-733a059cc15d1f317ac496d140bfd1dcc325a249.zip
FreeBSD-src-733a059cc15d1f317ac496d140bfd1dcc325a249.tar.gz
Reinstate revision 1.11:
BDECFLAGS; ANSIfy; use EXEC instead of "exec " where appropriate; use proper types (size_t, int); use proper variable names for certain things; get rid of static 'cache' style stuff by moving and sanitizing the original SHELL checking code to main(), this also makes it easier to free() the string; rename file-scope system() to exec_shell(); use snprintf() everywhere instead of sprintf(); actually remember to free() other malloc()'d char pointers in main(). I left out the -s option in this revision along with getusershell() checking because of objections made by Warner Losh <imp> and Garrett Wollman <wollman>. I agreed with their assertions that such code was unnecessary in a program like this. I dare people to make this coredump now. Some suggestions: nectar (snprintf() truncate checking) Reviewed by: markm, eivind, jedgar Tortured by: examples in apply(1), fuzz(1), and a lot of random ideas I came up with
Diffstat (limited to 'usr.bin/apply')
-rw-r--r--usr.bin/apply/apply.c99
1 files changed, 62 insertions, 37 deletions
diff --git a/usr.bin/apply/apply.c b/usr.bin/apply/apply.c
index 05e086d..70f3bdf 100644
--- a/usr.bin/apply/apply.c
+++ b/usr.bin/apply/apply.c
@@ -55,16 +55,16 @@ static const char rcsid[] =
#include <string.h>
#include <unistd.h>
-void usage __P((void));
-int system __P((const char *));
+void usage(void);
+static int exec_shell(char *, char *, const char *);
+
+#define EXEC "exec "
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, rval, offset;
+ size_t clen, l, cmdsize;
+ char *c, *cmd, *p, *q, *shell, *name, *tmpshell, *slashp;
debug = 0;
magic = '%'; /* Default magic char is `%'. */
@@ -109,13 +109,31 @@ main(argc, argv)
}
/*
+ * 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)
+ cmdsize = sizeof(EXEC) - 1 + strlen(argv[0]) + 9 *
+ (sizeof(" %1") - 1) + 1;
+ if ((cmd = malloc(cmdsize)) == NULL)
err(1, NULL);
if (n == 0) {
@@ -124,9 +142,16 @@ main(argc, argv)
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;
+ 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;
+ }
/*
* If nargs set to the special value 0, eat a single
@@ -135,7 +160,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;
}
@@ -164,9 +191,13 @@ main(argc, argv)
/* 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;
+ } else
*q++ = *p;
/* Terminate the command string. */
@@ -176,38 +207,32 @@ main(argc, argv)
if (debug)
(void)printf("%s\n", c);
else
- if (system(c))
+ if (exec_shell(shell, name, c))
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(char *use_shell, char *use_name, const char *command)
{
- static char *name, *shell;
pid_t pid;
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);
@@ -217,8 +242,8 @@ 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, NULL);
+ warn("%s", use_shell);
_exit(1);
}
intsave = signal(SIGINT, SIG_IGN);
OpenPOWER on IntegriCloud