Commit | Line | Data |
---|---|---|
9d25673b C |
1 | /* execve.c: an execve() for geriatric unices without #! */ |
2 | ||
3 | /* | |
4 | NOTE: this file depends on a hack in footobar.c which places two free spots before | |
5 | av[][] so that execve does not have to call malloc. | |
6 | */ | |
7 | ||
8 | #include <errno.h> | |
9 | #include "rc.h" | |
10 | ||
11 | #define giveupif(x) { if (x) goto fail; } | |
12 | ||
13 | extern int my_execve(const char *path, const char **av, const char **ev) { | |
14 | int fd, len, fst, snd, end; | |
15 | bool noarg; | |
16 | char pb[256]; /* arbitrary but generous limit */ | |
17 | execve(path, av, ev); | |
18 | if (errno != ENOEXEC) | |
19 | return -1; | |
20 | fd = rc_open(path, rFrom); | |
21 | giveupif(fd < 0); | |
22 | len = read(fd, pb, sizeof pb); | |
23 | close(fd); | |
24 | /* reject scripts which don't begin with #! */ | |
25 | giveupif(len <= 0 || pb[0] != '#' || pb[1] != '!'); | |
26 | for (fst = 2; fst < len && (pb[fst] == ' ' || pb[fst] == '\t'); fst++) | |
27 | ; /* skip leading whitespace */ | |
28 | giveupif(fst == len); | |
29 | for (snd = fst; snd < len && pb[snd] != ' ' && pb[snd] != '\t' && pb[snd] != '\n'; snd++) | |
30 | ; /* skip first arg */ | |
31 | giveupif(snd == len); | |
32 | noarg = (pb[snd] == '\n'); | |
33 | pb[snd++] = '\0'; /* null terminate the first arg */ | |
34 | if (!noarg) { | |
35 | while (snd < len && (pb[snd] == ' ' || pb[snd] == '\t')) | |
36 | snd++; /* skip whitespace to second arg */ | |
37 | giveupif(snd == len); | |
38 | noarg = (pb[snd] == '\n'); /* could have trailing whitespace after only one arg */ | |
39 | if (!noarg) { | |
40 | for (end = snd; end < len && pb[end] != ' ' && pb[end] != '\t' && pb[end] != '\n'; end++) | |
41 | ; /* skip to the end of the second arg */ | |
42 | giveupif(end == len); | |
43 | if (pb[end] == '\n') { | |
44 | pb[end] = '\0'; /* null terminate the first arg */ | |
45 | } else { /* else check for a spurious third arg */ | |
46 | pb[end++] = '\0'; | |
47 | while (end < len && (pb[end] == ' ' || pb[end] == '\t')) | |
48 | end++; | |
49 | giveupif(end == len || pb[end] != '\n'); | |
50 | } | |
51 | } | |
52 | } | |
53 | *av = path; | |
54 | if (!noarg) | |
55 | *--av = pb + snd; | |
56 | *--av = pb + fst; | |
57 | execve(*av, av, ev); | |
58 | return -1; | |
59 | fail: errno = ENOEXEC; | |
60 | return -1; | |
61 | } |