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: }

Defined functions

append defined in line 242; used 2 times
dotname defined in line 212; used 2 times
main defined in line 21; never used
rm defined in line 78; used 2 times
yes defined in line 229; used 4 times

Defined variables

errcode defined in line 17; used 8 times
fflg defined in line 13; used 11 times
iflg defined in line 14; used 7 times
path defined in line 71; used 9 times
pathp defined in line 72; used 11 times
pathsz defined in line 73; used 3 times
rflg defined in line 15; used 3 times
sccsid defined in line 1; never used
Last modified: 1986-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1563
Valid CSS Valid XHTML 1.0 Strict