mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-04 12:52:15 +00:00
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
This commit is contained in:
parent
c05aa33cb0
commit
f697348034
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=70692
@ -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 `%'. */
|
||||
@ -108,14 +108,32 @@ 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)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user