Annotation of researchv10no/cmd/rm.c, revision 1.1

1.1     ! root        1: #include <stdio.h>
        !             2: #include <sys/types.h>
        !             3: #include <ndir.h>
        !             4: #include <errno.h>
        !             5: 
        !             6: int fflag;
        !             7: int iflag;
        !             8: int rflag;
        !             9: int qflag;
        !            10: int errcnt;
        !            11: 
        !            12: extern char *strcpy(), *malloc(), *parent(), *child();
        !            13: 
        !            14: main(argc, argv)
        !            15: char **argv;
        !            16: {
        !            17:        for( ; argc>1 && *argv[1]=='-'; argc--, argv++) {
        !            18:                for(;;) {
        !            19:                        switch(*++argv[1]) {
        !            20:                        case 'f':
        !            21:                                fflag++;
        !            22:                                continue;
        !            23:                        case 'i':
        !            24:                                iflag++;
        !            25:                                continue;
        !            26:                        case 'r':
        !            27:                                rflag++;
        !            28:                                continue;
        !            29:                        default:
        !            30:                                usage();
        !            31:                        case 0: ;
        !            32:                        }
        !            33:                        break;
        !            34:                }
        !            35:        }
        !            36:        if(argc <= 1)
        !            37:                usage();
        !            38:        qflag = !fflag && !iflag && isatty(0);
        !            39:        while(--argc>0)
        !            40:                rm(*++argv);
        !            41:        return errcnt;
        !            42: }
        !            43: 
        !            44: usage()
        !            45: {
        !            46: 
        !            47:        fprintf(stderr, "usage: rm [-fri] file ...\n");
        !            48:        exit(1);
        !            49: }
        !            50: 
        !            51: /* To avoid unnecessarily raising the process label in secure unix,
        !            52:    rm() and recurse() are coded without stat().  Except when 
        !            53:    questions are asked, it takes between 1 and 6, typically 3,
        !            54:    system calls to remove a file.
        !            55: */
        !            56: rm(s)
        !            57: register char *s;
        !            58: {
        !            59:        if(strcmp(s, "..") == 0) {
        !            60:                errno = EINVAL;
        !            61:                error(s);
        !            62:                return;
        !            63:        }
        !            64:        if(iflag && access(parent(s),2)==0 && !query("%s: ", s) ||
        !            65:           qflag && access(s,2)==-1 &&
        !            66:           access(s,0)==0 && access(parent(s),2)==0 &&
        !            67:           !query("rm: %s unwritable; remove? ", s))
        !            68:                return;
        !            69:        /* Try rmdir first, to guard against superuser process
        !            70:           doing unlink on a directory, which would be bad.
        !            71:           Race conditions in which a directory might be unlinked:
        !            72:           (1) rmdir gives EBUSY; other proc cd's out before unlink
        !            73:           (2) rmdir gives EACCES; other proc changes parent's mode
        !            74:           (3) rmdir gives EPERM; other proc changes mode along path
        !            75:        */
        !            76:        if(rmdir(s) == 0)
        !            77:                return;
        !            78:        switch(errno) {
        !            79:        case EBUSY:     /* text file or working directory */
        !            80:        case EPERM:
        !            81:        case EACCES:    /* parent(s) unwritable; s may not be dir */
        !            82:                if(access(child(s),0) == 0)     /* s searchable? */
        !            83:                        goto case_ISDIR;
        !            84:        case ENOTDIR:
        !            85:                if(unlink(s) == 0)
        !            86:                        return;
        !            87:                break;
        !            88:        case_ISDIR:
        !            89:        case EHASF:
        !            90:        case EINVAL:    /* file name "." */
        !            91:                if(rflag) {
        !            92:                        recurse(s);
        !            93:                        return;
        !            94:                }
        !            95:        }
        !            96:        error(s);
        !            97: }
        !            98: 
        !            99: recurse(s)
        !           100: char *s;
        !           101: {
        !           102:        register struct direct *entryp;
        !           103:        register DIR *dirp = opendir(s);
        !           104:        char *path;
        !           105: 
        !           106:        if(dirp == 0) {
        !           107:                error(s);
        !           108:                return;
        !           109:        }
        !           110:        path = malloc(strlen(s)+MAXNAMLEN+2);
        !           111:        while(entryp = readdir(dirp)) {
        !           112:                char *ep = entryp->d_name;
        !           113:                if(strcmp(ep,".")==0 || strcmp(ep,"..")==0)
        !           114:                        continue;
        !           115:                sprintf(path, "%s/%s", s, ep);
        !           116:                rm(path);
        !           117:        }
        !           118:        free(path);
        !           119:        closedir(dirp);
        !           120:        if(rmdir(s) == -1)
        !           121:                error(s);
        !           122: }
        !           123: 
        !           124: error(s)
        !           125: char *s;
        !           126: {
        !           127:        if(fflag) return;
        !           128:        fprintf(stderr, "rm: ");
        !           129:        perror(s);
        !           130:        errcnt++;
        !           131: }
        !           132: 
        !           133: query(f, s)
        !           134: char *f, *s;
        !           135: {
        !           136:        int c, reply;
        !           137: 
        !           138:        printf(f, s);
        !           139:        reply = c = getchar();
        !           140:        while(c != '\n') {
        !           141:                if(c == EOF)
        !           142:                        return 0;
        !           143:                c = getchar();
        !           144:        }
        !           145:        return reply == 'y';
        !           146: }
        !           147: 
        !           148: char *
        !           149: parent(s)
        !           150: register char *s;
        !           151: {
        !           152:        register n;
        !           153:        static char *p;
        !           154:        register char *t = s;
        !           155:        
        !           156:        while(*t)
        !           157:                t++;
        !           158:        while(t>s && t[-1]=='/')
        !           159:                t--;
        !           160:        while(t>s && t[-1]!='/')
        !           161:                t--;
        !           162:        if(t == s)
        !           163:                return ".";
        !           164:        while(t>s && t[-1]=='/')
        !           165:                t--;
        !           166:        if(t == s)
        !           167:                return "/";
        !           168:        n = t - s;
        !           169:        if(p) free(p);
        !           170:        p = malloc(n + 1);
        !           171:        strncpy(p, s, n);
        !           172:        p[n] = 0;
        !           173:        return p;
        !           174: }
        !           175: 
        !           176: char *
        !           177: child(s)
        !           178: char *s;
        !           179: {
        !           180:        static char *p;
        !           181:        if(p) free(p);
        !           182:        p = malloc(strlen(s)+MAXNAMLEN+2);
        !           183:        strcat(strcpy(p, s), "/.");
        !           184:        return p;
        !           185: }

unix.superglobalmegacorp.com

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