BDECFLAGS; de-__P()-ify, ANSIfy, use snprintf() instead of sprintf(),

especially on strings passed from argv; rename system() to exec_shell(),
and make it static; use strlcpy() and make sure it works; use proper
type (size_t) to be passed to malloc()/realloc().

Use getusershell() to make sure the SHELL environment variable passed is
safe to use.  Add new option -s to allow anal users to pass things like
perl; this option is here along with getusershell() checking since the
such checking is only intended to affect things like suidperl that might
call apply(1).

Reviewed by:	markm, jhb, C. Stephen Gunn <csg@waterspout.com>
This commit is contained in:
will 2001-01-04 19:05:49 +00:00
parent eace534ae0
commit 92681d841a

View File

@ -55,21 +55,23 @@ 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 (const char *);
static unsigned int prespecified;
static char *shell;
int
main(argc, argv)
int argc;
char *argv[];
main(int argc, char **argv)
{
int ch, clen, debug, i, l, magic, n, nargs, rval;
int ch, debug, i, magic, n, nargs, rval;
size_t clen, l;
char *c, *cmd, *p, *q;
debug = 0;
magic = '%'; /* Default magic char is `%'. */
nargs = -1;
while ((ch = getopt(argc, argv, "a:d0123456789")) != -1)
while ((ch = getopt(argc, argv, "a:ds:0123456789")) != -1)
switch (ch) {
case 'a':
if (optarg[1] != '\0')
@ -80,6 +82,10 @@ main(argc, argv)
case 'd':
debug = 1;
break;
case 's':
prespecified = 1;
shell = optarg;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (nargs != -1)
@ -124,9 +130,9 @@ main(argc, argv)
nargs = 1;
p = cmd;
p += sprintf(cmd, "exec %s", argv[0]);
p += snprintf(cmd, sizeof(cmd), "exec %s", argv[0]);
for (i = 1; i <= nargs; i++)
p += sprintf(p, " %c%d", magic, i);
p += snprintf(p, sizeof(p), " %c%d", magic, i);
/*
* If nargs set to the special value 0, eat a single
@ -135,7 +141,7 @@ main(argc, argv)
if (nargs == 0)
nargs = 1;
} else {
(void)sprintf(cmd, "exec %s", argv[0]);
(void)snprintf(cmd, sizeof(cmd), "exec %s", argv[0]);
nargs = n;
}
@ -165,7 +171,7 @@ 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']);
q += snprintf(q, sizeof(q), "%s", argv[(++p)[0] - '0']);
else
*q++ = *p;
@ -176,7 +182,7 @@ main(argc, argv)
if (debug)
(void)printf("%s\n", c);
else
if (system(c))
if (exec_shell(c))
rval = 1;
}
@ -187,28 +193,39 @@ main(argc, argv)
}
/*
* system --
* exec_shell --
* Private version of system(3). Use the user's SHELL environment
* variable as the shell to execute.
*/
int
system(command)
const char *command;
static int
exec_shell(const char *command)
{
static char *name, *shell;
static char *name;
char *tmpshell;
pid_t pid;
int omask, pstat;
sig_t intsave, quitsave;
unsigned int okshell = 0;
if (shell == NULL) {
if ((shell = getenv("SHELL")) == NULL)
shell = _PATH_BSHELL;
if ((name = strrchr(shell, '/')) == NULL)
name = shell;
else
if (strlcpy(shell, _PATH_BSHELL, sizeof(shell)) != strlen(shell))
err(1, "strlcpy() failed");
if ((name = strrchr(shell, '/')) == NULL) {
if (strlcpy(name, shell, sizeof(name)) != strlen(shell))
err(1, "strlcpy() failed");
} else {
++name;
}
}
if (!command) /* just checking... */
/* Now double-check to make sure the shell is friendly */
if (!prespecified)
while((tmpshell = getusershell()) != NULL)
if (strcmp((const char *)tmpshell, (const char *)shell) == 0)
okshell = 1;
if (!command || !okshell) /* just checking... */
return(1);
omask = sigblock(sigmask(SIGCHLD));
@ -235,6 +252,6 @@ usage()
{
(void)fprintf(stderr,
"usage: apply [-a magic] [-d] [-0123456789] command arguments ...\n");
"usage: apply [-a magic] [-d] [-s shell] [-0123456789] command arguments ...\n");
exit(1);
}