Annotation of researchv10no/cmd/rm.c, revision 1.1.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.