|
|
1.1 ! root 1: /* ! 2: * libc/sys/i386/execve.c ! 3: * This version of execve() understands "#!interpreter [ arg ...]\n" lines. ! 4: * The original version of this source was "iexec.c" Version 1.6, ! 5: * written by David MacKenzie <[email protected]> and placed in the public domain. ! 6: * Extensively modified by steve 8/12/92 for COHERENT. ! 7: */ ! 8: ! 9: #include <errno.h> ! 10: #include <string.h> ! 11: #include <stdlib.h> ! 12: #include <fcntl.h> ! 13: ! 14: #define MAXLINELEN 512 /* bytes to read from first line of a script */ ! 15: #define iswhite(c) ((c) == ' ' || (c) == '\t') /* whitespace */ ! 16: ! 17: /* Try _execve(), i.e. sys exec; then try running as a script if it fails. */ ! 18: int ! 19: execve(cmd, argv, envp) char *cmd; char **argv; char **envp; ! 20: { ! 21: ! 22: if (_execve(cmd, argv, envp) == -1 && errno == ENOEXEC) { ! 23: script_execve(cmd, argv, envp); ! 24: errno = ENOEXEC; ! 25: } ! 26: return -1; ! 27: } ! 28: ! 29: /* ! 30: * If 'file' is a script which begins "#!interp [ arg ...]\n", ! 31: * set 'interp' to the name of the program that should run it ! 32: * and 'int_args' to the given args (or NULL if none). ! 33: * Create a new argument list containing 'interp', ! 34: * expanded 'int_args' (if non-NULL), 'file', and the original argv. ! 35: * Then try to run 'interp' with the new argument list and 'envp'. ! 36: * Return -1 if it fails. ! 37: */ ! 38: static ! 39: int ! 40: script_execve(file, argv, envp) char *file, **argv, **envp; ! 41: { ! 42: char line[MAXLINELEN + 1]; ! 43: register char *cp, **ap, **nargv; ! 44: char *interp, *int_args; ! 45: register int argc, fd, n; ! 46: char c, inquote; ! 47: ! 48: /* Open the file, read a chunk, see how it starts. */ ! 49: if ((fd = open(file, O_RDONLY, 0)) == -1) ! 50: return -1; ! 51: n = read(fd, line, MAXLINELEN); ! 52: if (close(fd) == -1 || n < 4 || line[0] != '#' || line[1] != '!') ! 53: return -1; ! 54: ! 55: /* The first line looks appropriate. */ ! 56: line[n] = '\0'; /* NUL-terminate */ ! 57: if ((cp = strchr(line, '\n')) == NULL) ! 58: return -1; ! 59: *cp = '\0'; /* zap newline */ ! 60: ! 61: /* Find interpreter name and args. */ ! 62: for (cp = line + 2; iswhite(*cp); ++cp) ! 63: ; /* skip whitespace after #! */ ! 64: if (*cp == '\0') ! 65: return -1; ! 66: interp = cp; /* interpreter name */ ! 67: for (; *cp != '\0' && !iswhite(*cp); ++cp) ! 68: ; /* scan to whitespace or NUL */ ! 69: if (*cp == '\0') ! 70: int_args = NULL; ! 71: else { ! 72: *cp++ = '\0'; /* NUL-terminate name */ ! 73: int_args = cp; /* interpreter args */ ! 74: } ! 75: ! 76: /* Find new arg count max and allocate space for new argv. */ ! 77: for (argc = 2, ap = argv; *ap != NULL; ++ap) ! 78: ++argc; /* count old argv args + 1 */ ! 79: if (int_args != NULL) ! 80: argc += strlen(int_args)/2; /* add max int_args args */ ! 81: if ((nargv = (char **)malloc(sizeof(char *) * argc)) == NULL) ! 82: return -1; ! 83: ! 84: /* Initialize the new argv. */ ! 85: argc = 0; ! 86: nargv[argc++] = interp; /* interpreter name */ ! 87: if (int_args != NULL) { ! 88: ! 89: /* Add whitespace-separated args from int_args. */ ! 90: for (cp = int_args; (c = *cp) != '\0'; ) { ! 91: while (iswhite(c)) ! 92: c = *++cp; /* skip whitespace */ ! 93: if (c == '\0') ! 94: break; ! 95: else if (c == '\'' || c == '"') { ! 96: inquote = c; /* quoted arg */ ! 97: ++cp; ! 98: } else ! 99: inquote = 0; ! 100: nargv[argc++] = cp; /* start new arg */ ! 101: while ((c = *cp++) != '\0') { ! 102: if (!inquote && iswhite(c)) ! 103: break; ! 104: else if (inquote && c == inquote) { ! 105: inquote = cp[-1] = '\0'; /* zap close quote */ ! 106: c = *cp++; /* next char */ ! 107: break; ! 108: } ! 109: } ! 110: if (inquote) { ! 111: free(nargv); ! 112: return -1; /* fail on missing close quote */ ! 113: } else if (c == '\0') ! 114: break; ! 115: else ! 116: cp[-1] = '\0'; /* NUL-terminate arg */ ! 117: } ! 118: } ! 119: nargv[argc++] = file; /* script name */ ! 120: ! 121: /* Copy the old arguments. */ ! 122: for (ap = argv + 1; *ap != NULL; ++ap) ! 123: nargv[argc++] = *ap; ! 124: nargv[argc] = NULL; ! 125: ! 126: /* Go for smoke. */ ! 127: _execve(interp, nargv, envp); ! 128: free(nargv); ! 129: return -1; ! 130: } ! 131: ! 132: /* end of libc/sys/i386/execve.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.