summaryrefslogtreecommitdiff
path: root/execve.c
diff options
context:
space:
mode:
authorByron Rakitzis <byron@archone.tamu.edu>1992-05-27 00:00:01 +0100
committerToby Goodwin <toby@paccrat.org>2015-05-16 21:22:56 +0100
commit26bb34cf036027dfa22dfae8d8fc2f6bfd6acb75 (patch)
tree589705b2492ce4681760846d9ca45600f0af298d /execve.c
release: rc-1.4
Diffstat (limited to 'execve.c')
-rw-r--r--execve.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/execve.c b/execve.c
new file mode 100644
index 0000000..b21b30c
--- /dev/null
+++ b/execve.c
@@ -0,0 +1,61 @@
+/* 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 <errno.h>
+#include "rc.h"
+
+#define giveupif(x) { if (x) goto fail; }
+
+extern int my_execve(const char *path, const char **av, const 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;
+}