=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/make/cmd_exec.c,v retrieving revision 1.11 retrieving revision 1.12 diff -c -r1.11 -r1.12 *** src/usr.bin/make/cmd_exec.c 2020/01/16 16:07:18 1.11 --- src/usr.bin/make/cmd_exec.c 2023/08/31 06:53:28 1.12 *************** *** 1,4 **** ! /* $OpenBSD: cmd_exec.c,v 1.11 2020/01/16 16:07:18 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. * --- 1,4 ---- ! /* $OpenBSD: cmd_exec.c,v 1.12 2023/08/31 06:53:28 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. * *************** *** 28,33 **** --- 28,34 ---- #include #include #include + #include #include #include "config.h" #include "defines.h" *************** *** 36,46 **** #include "memory.h" #include "pathnames.h" #include "job.h" char * Cmd_Exec(const char *cmd, char **err) { - char *args[4]; /* Args for invoking the shell */ int fds[2]; /* Pipe streams */ pid_t cpid; /* Child PID */ char *result; /* Result */ --- 37,129 ---- #include "memory.h" #include "pathnames.h" #include "job.h" + #include "str.h" + /* The following array is used to make a fast determination of which + * characters are interpreted specially by the shell. If a command + * contains any of these characters, it is executed by the shell, not + * directly by us. */ + static char meta[256]; + + void + CmdExec_Init(void) + { + char *p; + + for (p = "#=|^(){};&<>*?[]:$`\\\n~"; *p != '\0'; p++) + meta[(unsigned char) *p] = 1; + /* The null character serves as a sentinel in the string. */ + meta[0] = 1; + } + + static char ** + recheck_command_for_shell(char **av) + { + char *runsh[] = { + "!", "alias", "cd", "eval", "exit", "read", "set", "ulimit", + "unalias", "unset", "wait", "umask", NULL + }; + + char **p; + + /* optimization: if exec cmd, we avoid the intermediate shell */ + if (strcmp(av[0], "exec") == 0) + av++; + + if (!av[0]) + return NULL; + + for (p = runsh; *p; p++) + if (strcmp(av[0], *p) == 0) + return NULL; + + return av; + } + + void + run_command(const char *cmd, bool errCheck) + { + const char *p; + char *shargv[4]; + char **todo; + + shargv[0] = _PATH_BSHELL; + + shargv[1] = errCheck ? "-ec" : "-c"; + shargv[2] = (char *)cmd; + shargv[3] = NULL; + + todo = shargv; + + + /* Search for meta characters in the command. If there are no meta + * characters, there's no need to execute a shell to execute the + * command. */ + for (p = cmd; !meta[(unsigned char)*p]; p++) + continue; + if (*p == '\0') { + char *bp; + char **av; + int argc; + /* No meta-characters, so probably no need to exec a shell. + * Break the command into words to form an argument vector + * we can execute. */ + av = brk_string(cmd, &argc, &bp); + av = recheck_command_for_shell(av); + if (av != NULL) + todo = av; + } + execvp(todo[0], todo); + if (errno == ENOENT) + fprintf(stderr, "%s: not found\n", todo[0]); + else + perror(todo[0]); + _exit(1); + } + char * Cmd_Exec(const char *cmd, char **err) { int fds[2]; /* Pipe streams */ pid_t cpid; /* Child PID */ char *result; /* Result */ *************** *** 53,64 **** *err = NULL; - /* Set up arguments for the shell. */ - args[0] = "sh"; - args[1] = "-c"; - args[2] = (char *)cmd; - args[3] = NULL; - /* Open a pipe for retrieving shell's output. */ if (pipe(fds) == -1) { *err = "Couldn't create pipe for \"%s\""; --- 136,141 ---- *************** *** 82,89 **** (void)close(fds[1]); } ! (void)execv(_PATH_BSHELL, args); ! _exit(1); /*NOTREACHED*/ case -1: --- 159,165 ---- (void)close(fds[1]); } ! run_command(cmd, false); /*NOTREACHED*/ case -1: