|
|
1.1 ! root 1: static char *sccsid = "@(#)rm.c 4.18 (Berkeley) 1/6/86"; ! 2: ! 3: /* ! 4: * rm - for ReMoving files, directories & trees. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <sys/param.h> ! 9: #include <sys/stat.h> ! 10: #include <sys/dir.h> ! 11: #include <sys/file.h> ! 12: ! 13: int fflg; /* -f force - supress error messages */ ! 14: int iflg; /* -i interrogate user on each file */ ! 15: int rflg; /* -r recurse */ ! 16: ! 17: int errcode; /* true if errors occured */ ! 18: ! 19: char *strcpy(), *malloc(), *realloc(); ! 20: ! 21: main(argc, argv) ! 22: char *argv[]; ! 23: { ! 24: register char *arg; ! 25: ! 26: fflg = !isatty(0); ! 27: iflg = 0; ! 28: rflg = 0; ! 29: while (argc > 1 && argv[1][0] == '-') { ! 30: arg = *++argv; ! 31: argc--; ! 32: ! 33: /* ! 34: * all files following a null option are considered file names ! 35: */ ! 36: if (arg[1] == '\0') ! 37: break; ! 38: ! 39: while (*++arg != '\0') ! 40: switch(*arg) { ! 41: case 'f': ! 42: fflg++; ! 43: break; ! 44: ! 45: case 'i': ! 46: iflg++; ! 47: break; ! 48: ! 49: case 'R': ! 50: case 'r': ! 51: rflg++; ! 52: break; ! 53: ! 54: default: ! 55: fprintf(stderr, "usage: rm [-rif] file ...\n"); ! 56: exit(1); ! 57: } ! 58: } ! 59: ! 60: if (argc < 2 && !fflg) { ! 61: fprintf(stderr, "usage: rm [-rif] file ...\n"); ! 62: exit(1); ! 63: } ! 64: ! 65: while (--argc > 0) ! 66: (void) rm(*++argv, 0); ! 67: ! 68: exit(errcode != 0); ! 69: } ! 70: ! 71: char *path; /* pointer to malloc'ed buffer for path */ ! 72: char *pathp; /* current pointer to end of path */ ! 73: int pathsz; /* size of path */ ! 74: ! 75: /* ! 76: * Return TRUE if sucessful. Recursive with -r (rflg) ! 77: */ ! 78: rm(arg, level) ! 79: char arg[]; ! 80: { ! 81: int ok; /* true if recursive rm succeeded */ ! 82: struct stat buf; /* for finding out what a file is */ ! 83: struct direct *dp; /* for reading a directory */ ! 84: DIR *dirp; /* for reading a directory */ ! 85: char prevname[MAXNAMLEN + 1]; /* previous name for -r */ ! 86: char *cp; ! 87: ! 88: if (dotname(arg)) { ! 89: fprintf(stderr, "rm: cannot remove `.' or `..'\n"); ! 90: return (0); ! 91: } ! 92: if (lstat(arg, &buf)) { ! 93: if (!fflg) { ! 94: fprintf(stderr, "rm: %s nonexistent\n", arg); ! 95: errcode++; ! 96: } ! 97: return (0); /* error */ ! 98: } ! 99: if ((buf.st_mode&S_IFMT) == S_IFDIR) { ! 100: if (!rflg) { ! 101: if (!fflg) { ! 102: fprintf(stderr, "rm: %s directory\n", arg); ! 103: errcode++; ! 104: } ! 105: return (0); ! 106: } ! 107: if (iflg && level != 0) { ! 108: printf("rm: remove directory %s? ", arg); ! 109: if (!yes()) ! 110: return (0); /* didn't remove everything */ ! 111: } ! 112: if (access(arg, R_OK|W_OK|X_OK) != 0) { ! 113: if (rmdir(arg) == 0) ! 114: return (1); /* salvaged: removed empty dir */ ! 115: if (!fflg) { ! 116: fprintf(stderr, "rm: %s not changed\n", arg); ! 117: errcode++; ! 118: } ! 119: return (0); /* error */ ! 120: } ! 121: if ((dirp = opendir(arg)) == NULL) { ! 122: if (!fflg) { ! 123: fprintf(stderr, "rm: cannot read %s?\n", arg); ! 124: errcode++; ! 125: } ! 126: return (0); ! 127: } ! 128: if (level == 0) ! 129: append(arg); ! 130: prevname[0] = '\0'; ! 131: while ((dp = readdir(dirp)) != NULL) { ! 132: if (dotname(dp->d_name)) { ! 133: strcpy(prevname, dp->d_name); ! 134: continue; ! 135: } ! 136: append(dp->d_name); ! 137: closedir(dirp); ! 138: ok = rm(path, level + 1); ! 139: for (cp = pathp; *--cp != '/' && cp > path; ) ! 140: ; ! 141: pathp = cp; ! 142: *cp++ = '\0'; ! 143: if ((dirp = opendir(arg)) == NULL) { ! 144: if (!fflg) { ! 145: fprintf(stderr, "rm: cannot read %s?\n", arg); ! 146: errcode++; ! 147: } ! 148: break; ! 149: } ! 150: /* pick up where we left off */ ! 151: if (prevname[0] != '\0') { ! 152: while ((dp = readdir(dirp)) != NULL && ! 153: strcmp(prevname, dp->d_name) != 0) ! 154: ; ! 155: } ! 156: /* skip the one we just failed to delete */ ! 157: if (!ok) { ! 158: dp = readdir(dirp); ! 159: if (dp != NULL && strcmp(cp, dp->d_name)) { ! 160: fprintf(stderr, ! 161: "rm: internal synchronization error: %s, %s, %s\n", ! 162: arg, cp, dp->d_name); ! 163: } ! 164: strcpy(prevname, dp->d_name); ! 165: } ! 166: } ! 167: closedir(dirp); ! 168: if (level == 0) { ! 169: pathp = path; ! 170: *pathp = '\0'; ! 171: } ! 172: if (iflg) { ! 173: printf("rm: remove %s? ", arg); ! 174: if (!yes()) ! 175: return (0); ! 176: } ! 177: if (rmdir(arg) < 0) { ! 178: if (!fflg || iflg) { ! 179: fprintf(stderr, "rm: %s not removed\n", arg); ! 180: errcode++; ! 181: } ! 182: return (0); ! 183: } ! 184: return (1); ! 185: } ! 186: ! 187: if (iflg) { ! 188: printf("rm: remove %s? ", arg); ! 189: if (!yes()) ! 190: return (0); ! 191: } else if (!fflg) { ! 192: if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, W_OK) < 0) { ! 193: printf("rm: override protection %o for %s? ", ! 194: buf.st_mode&0777, arg); ! 195: if (!yes()) ! 196: return (0); ! 197: } ! 198: } ! 199: if (unlink(arg) < 0) { ! 200: if (!fflg || iflg) { ! 201: fprintf(stderr, "rm: %s not removed\n", arg); ! 202: errcode++; ! 203: } ! 204: return (0); ! 205: } ! 206: return (1); ! 207: } ! 208: ! 209: /* ! 210: * boolean: is it "." or ".." ? ! 211: */ ! 212: dotname(s) ! 213: char *s; ! 214: { ! 215: if (s[0] == '.') ! 216: if (s[1] == '.') ! 217: if (s[2] == '\0') ! 218: return (1); ! 219: else ! 220: return (0); ! 221: else if (s[1] == '\0') ! 222: return (1); ! 223: return (0); ! 224: } ! 225: ! 226: /* ! 227: * Get a yes/no answer from the user. ! 228: */ ! 229: yes() ! 230: { ! 231: int i, b; ! 232: ! 233: i = b = getchar(); ! 234: while (b != '\n' && b != EOF) ! 235: b = getchar(); ! 236: return (i == 'y'); ! 237: } ! 238: ! 239: /* ! 240: * Append 'name' to 'path'. ! 241: */ ! 242: append(name) ! 243: char *name; ! 244: { ! 245: register int n; ! 246: ! 247: n = strlen(name); ! 248: if (path == NULL) { ! 249: pathsz = MAXNAMLEN + MAXPATHLEN + 2; ! 250: if ((path = malloc(pathsz)) == NULL) { ! 251: fprintf(stderr, "rm: ran out of memory\n"); ! 252: exit(1); ! 253: } ! 254: pathp = path; ! 255: } else if (pathp + n + 2 > path + pathsz) { ! 256: fprintf(stderr, "rm: path name too long: %s\n", path); ! 257: exit(1); ! 258: } else if (pathp != path && pathp[-1] != '/') ! 259: *pathp++ = '/'; ! 260: strcpy(pathp, name); ! 261: pathp += n; ! 262: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.