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