|
|
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.