File: execve.c

package info (click to toggle)
rc 1.7.2-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,084 kB
  • ctags: 1,050
  • sloc: ansic: 7,631; sh: 1,123; yacc: 124; makefile: 100; perl: 13
file content (62 lines) | stat: -rw-r--r-- 1,872 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* execve.c: an execve() for geriatric unices without #! */

/*
   NOTE: this file depends on a hack in footobar.c which places two free
   spots before av[][] so that execve does not have to call malloc.
*/

#include "rc.h"

#include <errno.h>

#define giveupif(x) { if (x) goto fail; }

extern int rc_execve(char *path, char **av, char **ev) {
	int fd, len, fst, snd, end;
	bool noarg;
	char pb[256]; /* arbitrary but generous limit */
	execve(path, av, ev);
	if (errno != ENOEXEC)
		return -1;
	fd = rc_open(path, rFrom);
	giveupif(fd < 0);
	len = read(fd, pb, sizeof pb);
	close(fd);
	/* reject scripts which don't begin with #! */
	giveupif(len <= 0 || pb[0] != '#' || pb[1] != '!');
	for (fst = 2; fst < len && (pb[fst] == ' ' || pb[fst] == '\t'); fst++)
		; /* skip leading whitespace */
	giveupif(fst == len);
	for (snd = fst; snd < len && pb[snd] != ' ' && pb[snd] != '\t' && pb[snd] != '\n'; snd++)
		; /* skip first arg */
	giveupif(snd == len);
	noarg = (pb[snd] == '\n');
	pb[snd++] = '\0'; /* null terminate the first arg */
	if (!noarg) {
		while (snd < len && (pb[snd] == ' ' || pb[snd] == '\t'))
			snd++; /* skip whitespace to second arg */
		giveupif(snd == len);
		noarg = (pb[snd] == '\n'); /* could have trailing whitespace after only one arg */
		if (!noarg) {
			for (end = snd; end < len && pb[end] != ' ' && pb[end] != '\t' && pb[end] != '\n'; end++)
				; /* skip to the end of the second arg */
			giveupif(end == len);
			if (pb[end] == '\n') {
				pb[end] = '\0'; /* null terminate the first arg */
			} else {		/* else check for a spurious third arg */
				pb[end++] = '\0';
				while (end < len && (pb[end] == ' ' || pb[end] == '\t'))
					end++;
				giveupif(end == len || pb[end] != '\n');
			}
		}
	}
	*av = path;
	if (!noarg)
		*--av = pb + snd;
	*--av = pb + fst;
	execve(*av, av, ev);
	return -1;
fail:	errno = ENOEXEC;
	return -1;
}