|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.