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:
parent
94648ce60d
commit
c494ed80cd
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user