|
|
1.1 root 1: /*
2: * libc/sys/i386/execve.c
3: * This version of execve() understands "#!interpreter [ arg ...]\n" lines.
4: * The original version of this source was "iexec.c" Version 1.6,
5: * written by David MacKenzie <[email protected]> and placed in the public domain.
6: * Extensively modified by steve 8/12/92 for COHERENT.
7: */
8:
9: #include <errno.h>
10: #include <string.h>
11: #include <stdlib.h>
12: #include <fcntl.h>
13:
14: #define MAXLINELEN 512 /* bytes to read from first line of a script */
15: #define iswhite(c) ((c) == ' ' || (c) == '\t') /* whitespace */
16:
17: /* Try _execve(), i.e. sys exec; then try running as a script if it fails. */
18: int
19: execve(cmd, argv, envp) char *cmd; char **argv; char **envp;
20: {
21:
22: if (_execve(cmd, argv, envp) == -1 && errno == ENOEXEC) {
23: script_execve(cmd, argv, envp);
24: errno = ENOEXEC;
25: }
26: return -1;
27: }
28:
29: /*
30: * If 'file' is a script which begins "#!interp [ arg ...]\n",
31: * set 'interp' to the name of the program that should run it
32: * and 'int_args' to the given args (or NULL if none).
33: * Create a new argument list containing 'interp',
34: * expanded 'int_args' (if non-NULL), 'file', and the original argv.
35: * Then try to run 'interp' with the new argument list and 'envp'.
36: * Return -1 if it fails.
37: */
38: static
39: int
40: script_execve(file, argv, envp) char *file, **argv, **envp;
41: {
42: char line[MAXLINELEN + 1];
43: register char *cp, **ap, **nargv;
44: char *interp, *int_args;
45: register int argc, fd, n;
46: char c, inquote;
47:
48: /* Open the file, read a chunk, see how it starts. */
49: if ((fd = open(file, O_RDONLY, 0)) == -1)
50: return -1;
51: n = read(fd, line, MAXLINELEN);
52: if (close(fd) == -1 || n < 4 || line[0] != '#' || line[1] != '!')
53: return -1;
54:
55: /* The first line looks appropriate. */
56: line[n] = '\0'; /* NUL-terminate */
57: if ((cp = strchr(line, '\n')) == NULL)
58: return -1;
59: *cp = '\0'; /* zap newline */
60:
61: /* Find interpreter name and args. */
62: for (cp = line + 2; iswhite(*cp); ++cp)
63: ; /* skip whitespace after #! */
64: if (*cp == '\0')
65: return -1;
66: interp = cp; /* interpreter name */
67: for (; *cp != '\0' && !iswhite(*cp); ++cp)
68: ; /* scan to whitespace or NUL */
69: if (*cp == '\0')
70: int_args = NULL;
71: else {
72: *cp++ = '\0'; /* NUL-terminate name */
73: int_args = cp; /* interpreter args */
74: }
75:
76: /* Find new arg count max and allocate space for new argv. */
77: for (argc = 2, ap = argv; *ap != NULL; ++ap)
78: ++argc; /* count old argv args + 1 */
79: if (int_args != NULL)
80: argc += strlen(int_args)/2; /* add max int_args args */
81: if ((nargv = (char **)malloc(sizeof(char *) * argc)) == NULL)
82: return -1;
83:
84: /* Initialize the new argv. */
85: argc = 0;
86: nargv[argc++] = interp; /* interpreter name */
87: if (int_args != NULL) {
88:
89: /* Add whitespace-separated args from int_args. */
90: for (cp = int_args; (c = *cp) != '\0'; ) {
91: while (iswhite(c))
92: c = *++cp; /* skip whitespace */
93: if (c == '\0')
94: break;
95: else if (c == '\'' || c == '"') {
96: inquote = c; /* quoted arg */
97: ++cp;
98: } else
99: inquote = 0;
100: nargv[argc++] = cp; /* start new arg */
101: while ((c = *cp++) != '\0') {
102: if (!inquote && iswhite(c))
103: break;
104: else if (inquote && c == inquote) {
105: inquote = cp[-1] = '\0'; /* zap close quote */
106: c = *cp++; /* next char */
107: break;
108: }
109: }
110: if (inquote) {
111: free(nargv);
112: return -1; /* fail on missing close quote */
113: } else if (c == '\0')
114: break;
115: else
116: cp[-1] = '\0'; /* NUL-terminate arg */
117: }
118: }
119: nargv[argc++] = file; /* script name */
120:
121: /* Copy the old arguments. */
122: for (ap = argv + 1; *ap != NULL; ++ap)
123: nargv[argc++] = *ap;
124: nargv[argc] = NULL;
125:
126: /* Go for smoke. */
127: _execve(interp, nargv, envp);
128: free(nargv);
129: return -1;
130: }
131:
132: /* end of libc/sys/i386/execve.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.