rc

[fork] interactive rc shell
git clone https://hhvn.uk/rc
git clone git://hhvn.uk/rc
Log | Files | Refs | README | LICENSE

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 }