Annotation of coherent/b/lib/libc/sys/execve.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.