Annotation of researchv8dc/cmd/uucp/expfile.c, revision 1.1.1.1

1.1       root        1: /*     /sccs/src/cmd/uucp/s.expfile.c
                      2:        expfile.c       1.4     8/30/84 17:37:18
                      3: */
                      4: #include "uucp.h"
                      5: VERSION(@(#)expfile.c  1.4);
                      6: 
                      7: /*
                      8:  * expand file name expansion is based on first characters
                      9:  *     /       -> fully qualified pathname. no
                     10:  *                processing necessary
                     11:  *     ~       -> prepended with login directory
                     12:  *     ~/      -> prepended with Pubdir
                     13:  *     default -> prepended with current directory
                     14:  *     file    -> filename to expand
                     15:  * returns: 
                     16:  *     0       -> ok
                     17:  *      FAIL   -> no Wrkdir name available
                     18:  */
                     19: expfile(file)
                     20: register char *file;
                     21: {
                     22:        register char *fpart, *up;
                     23:        int uid;
                     24:        char user[NAMESIZE], save[MAXFULLNAME];
                     25: 
                     26:        strcpy(save, file);
                     27:        if (*file == '/')
                     28:            ;
                     29:        else if (*file ==  '~') {
                     30:                /* find / and copy user part */
                     31:                for (fpart = save + 1, up = user; *fpart != '\0'
                     32:                        && *fpart != '/'; fpart++)
                     33:                                *up++ = *fpart;
                     34:                *up = '\0';
                     35:                if ((user[0]=='\0') || (gninfo(user, &uid, file) != 0)){
                     36:                        (void) strcpy(file, Pubdir);
                     37:                }
                     38:                (void) strcat(file, fpart);
                     39:        }
                     40:        else {
                     41:                (void) sprintf(file, "%s/%s", Wrkdir, save);
                     42:                if (Wrkdir[0] == '\0')
                     43:                        return(FAIL);
                     44:        }
                     45: 
                     46:        if (canPath(file) != 0) { /* I don't think this will ever fail */
                     47:                (void) strcpy(file, CORRUPTDIR);
                     48:                return(FAIL);
                     49:        }
                     50:        else
                     51:                return(0);
                     52: }
                     53: 
                     54: 
                     55: /*
                     56:  * make all necessary directories
                     57:  *     name    -> directory to make
                     58:  * return: 
                     59:  *     0       -> success
                     60:  *     FAIL    -> failure
                     61:  */
                     62: mkdirs(name)
                     63: register char *name;
                     64: {
                     65:        register char *p;
                     66:        char dir[MAXFULLNAME];
                     67: 
                     68:        strcpy(dir, name);
                     69:        if (*LASTCHAR(dir) != '/')
                     70:                (void) strcat(dir, "/");
                     71:        p = dir + 1;
                     72:        while (1) {
                     73:            if ((p = strchr(p, '/')) == NULL)
                     74:                return(0);
                     75:            *p = '\0';
                     76:            DEBUG(4, "mkdir - %s\n", dir);
                     77:            if (mkdirs2(dir, 0) == FAIL)
                     78:                return (FAIL);
                     79:            *p++ = '/';
                     80:        }
                     81: }
                     82: 
                     83: 
                     84: #ifdef ATTSV
                     85: /*
                     86:  * Make name a directory if it is not already a directory
                     87:  * ATTSV handling of setuid is less than convenient ...
                     88:  * return:
                     89:  *     0 -> ok
                     90:  *     FAIL -> failed
                     91:  */
                     92: 
                     93: mkdirs2(name, mask)
                     94: register char  *name;
                     95: register int   mask;
                     96: {
                     97:        int     ret, pid, status;
                     98:        char    *tail, nmbuf[MAXFULLNAME], *parent;
                     99:        struct stat     statbuf;
                    100: 
                    101:        if (DIRECTORY(name))
                    102:                return(0);              /* directory exists */
                    103: 
                    104:        /* in ATTSV the parent directory has to be writeable by real uid */
                    105:        (void) strcpy(nmbuf, name);
                    106: 
                    107:        /* get pathname of parent */
                    108:        tail = nmbuf + strlen(nmbuf) - 1;       /* last char in nmbuf */
                    109:        while (*tail == '/' && tail > nmbuf)    /* kill trailing slashes */
                    110:                *tail-- = '\0';
                    111: 
                    112:        /* is parent "."? */
                    113:        if ((tail = strrchr(nmbuf, '/')) != NULL) {
                    114:                *tail = '\0';
                    115:                parent = nmbuf;
                    116:        } else
                    117:                parent = ".";
                    118: 
                    119:        /* save mode of parent */
                    120:        if (stat(parent, &statbuf) != 0) {
                    121:            DEBUG(5, "CAN'T STAT PARENT DIRECTORY %s ", parent);
                    122:            DEBUG(5, "errno %d\n", errno);
                    123:            return(FAIL);
                    124:        }
                    125: 
                    126:        /* if it's already 0xx7 we don't have to change it */
                    127:        if ((statbuf.st_mode & 0777) != 0777) {
                    128:          /* make parent writable by all (thus by real uid) */
                    129:            if (chmod(parent, 0777) != 0) {
                    130:                DEBUG(5, "CAN'T CHMOD PARENT DIRECTORY %s ", parent);
                    131:                DEBUG(5, "errno %d\n", errno);
                    132:                return(FAIL);
                    133:            }
                    134:        }
                    135: 
                    136:        switch (pid = fork()) {
                    137:        case 0:                 /* child */
                    138:                umask(0);
                    139:                /* close stdout and stderr to fail quietly */
                    140:                close(1);
                    141:                close(2);
                    142:                execl("/bin/mkdir", "mkdir", name, 0);
                    143:                _exit(1);
                    144: 
                    145:        case -1:                /* fork failed */
                    146:                ASSERT(pid != -1, Ct_FORK, "mkdir", errno);
                    147: 
                    148:        default:                /* parent */
                    149:                break;
                    150:        }
                    151: 
                    152:        while ((ret = wait(&status)) != pid );
                    153: 
                    154:        if (status != 0) {
                    155:            errent(Ct_CREATE, name, ret, sccsid, __FILE__, __LINE__);
                    156:            return(FAIL);
                    157:        }
                    158: 
                    159: 
                    160:        if ((statbuf.st_mode & 0777) != 0777) {
                    161:          /* restore mode of parent directory */
                    162:            if (chmod(parent, statbuf.st_mode & 0777) != 0) {
                    163:                errent(Ct_CHMOD, parent, errno, sccsid, __FILE__, __LINE__);
                    164:                DEBUG(5, "CAN'T CHMOD PARENT %s\n", parent);
                    165:                return(FAIL);
                    166:            }
                    167:        }
                    168: 
                    169:        if (Uid != 0) {
                    170:                if (setuid(Uid) != 0) {
                    171:                    DEBUG(5, "CAN'T SETUID %d\n", Uid);
                    172:                    return(FAIL);
                    173:                }
                    174:                if ( chmod(name, (mask ^ 0777) & 0777) != 0) {
                    175:                    errent(Ct_CHMOD, name, errno, sccsid, __FILE__, __LINE__);
                    176:                    return(FAIL);
                    177:                };
                    178:                if (chown(name, UUCPUID, getgid()) != 0) {
                    179:                    DEBUG(5, "CHOWN FAILED %s  ", name);
                    180:                    DEBUG(5, "errno %d\n", errno);
                    181:                    errent(Ct_CHOWN, name, errno, sccsid, __FILE__, __LINE__);
                    182:                    setuid(Euid);
                    183:                    return(FAIL);
                    184:                }
                    185:                setuid(Euid);
                    186:        }
                    187:        return(0);
                    188: }
                    189: #endif ATTSV
                    190: 
                    191: #ifdef V7
                    192: mkdirs2(name, mask)
                    193: register char  *name;
                    194: register int   mask;
                    195: {
                    196:        int     ret;
                    197: 
                    198:        if (DIRECTORY(name))
                    199:                return(0);              /* directory exists */
                    200: 
                    201:        if (fork() == 0) {
                    202:                setuid(Euid);   /* this makes it trivial in V7 */
                    203:                umask(mask);
                    204:                /* close stdout and stderr to fail quietly */
                    205:                close(1);
                    206:                close(2);
                    207:                execl("/bin/mkdir", "mkdir", name, 0);
                    208:                _exit(1);
                    209:        }
                    210:        wait(&ret);
                    211: 
                    212:        if (ret != 0)           /* why should we abort if some remote tries */
                    213:            return(FAIL);       /* to make a garbage directory */
                    214: 
                    215:        return(0);
                    216: }
                    217: #endif V7
                    218: 
                    219: /*
                    220:  * expand file name and check return
                    221:  * print error if it failed.
                    222:  *     file    -> file name to check
                    223:  * returns: 
                    224:  *      0      -> ok
                    225:  *      FAIL   -> if expfile failed
                    226:  */
                    227: ckexpf(file)
                    228: char *file;
                    229: {
                    230:        if (expfile(file) == 0)
                    231:                return(0);
                    232: 
                    233:        fprintf(stderr, "Illegal filename (%s).\n", file);
                    234:        return(FAIL);
                    235: }
                    236: 
                    237: 
                    238: /*
                    239:  * make canonical path out of path passed as argument.
                    240:  *
                    241:  * Eliminate redundant self-references like // or /./
                    242:  * (A single terminal / will be preserved, however.)
                    243:  * Dispose of references to .. in the path names.
                    244:  * In relative path names, this means that .. or a/../..
                    245:  * will be treated as an illegal reference.
                    246:  * In full paths, .. is always allowed, with /.. treated as /
                    247:  *
                    248:  * returns:
                    249:  *     0       -> path is now in canonical form
                    250:  *     FAIL    -> relative path contained illegal .. reference
                    251:  */
                    252: 
                    253: int
                    254: canPath(path)
                    255: register char *path;   /* path is modified in place */
                    256: {
                    257:     register char *to, *fr;
                    258: 
                    259:     to = fr = path;
                    260:     if (*fr == '/') *to++ = *fr++;
                    261:     for (;;) {
                    262:        /* skip past references to self and validate references to .. */
                    263:        for (;;) {
                    264:            if (*fr == '/') {
                    265:                fr++;
                    266:                continue;
                    267:            }
                    268:            if ((strncmp(fr, "./", 2) == SAME) || EQUALS(fr, ".")) {
                    269:                fr++;
                    270:                continue;
                    271:            }
                    272:            if ((strncmp(fr, "../", 3) == SAME) || EQUALS(fr, "..")) {
                    273:                fr += 2;
                    274:                /*      /.. is /        */
                    275:                if (((to - 1) == path) && (*path == '/')) continue;
                    276:                /* error if no previous component */
                    277:                if (to <= path) return (FAIL);
                    278:                /* back past previous component */
                    279:                while ((--to > path) && (to[-1] != '/'));
                    280:                continue;
                    281:            }
                    282:            break;
                    283:        }
                    284:        /*
                    285:         * What follows is a legitimate component,
                    286:         * terminated by a null or a /
                    287:         */
                    288:        if (*fr == '\0') break;
                    289:        while ((*to++ = *fr) && (*fr++ != '/'));
                    290:     }
                    291:     /* null path is . */
                    292:     if (to == path) *to++ = '.';
                    293:     *to = '\0';
                    294:     return (0);
                    295: }

unix.superglobalmegacorp.com

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