1: /*
   2:  * Copyright (c) 1983 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)atrm.c	5.2 (Berkeley) 5/28/86";
  15: #endif not lint
  16: 
  17: /*
  18:  *	synopsis: atrm [-f] [-i] [-] [[job #] [user] ...]
  19:  *
  20:  *
  21:  *	Remove files from the directory /usr/spool/at. These files
  22:  *	represent jobs to be run at a later date.
  23:  *
  24:  *	Author: Steve Wall
  25:  *		Computer Systems Research Group
  26:  *		University of California @ Berkeley
  27:  *
  28:  */
  29: 
  30: #include <stdio.h>
  31: #include <pwd.h>
  32: #include <ctype.h>
  33: #include <sys/types.h>
  34: #include <sys/dir.h>
  35: #include <sys/file.h>
  36: #include <sys/stat.h>
  37: 
  38: #define SUPERUSER   0           /* is user super-user? */
  39: #define MAXENTRIES  1000            /* max # of entries allowed */
  40: #define ATDIR       "/usr/spool/at"     /* spooling area */
  41: 
  42: 
  43: int user;                   /* person requesting removal */
  44: int fflag = 0;                  /* suppress announcements? */
  45: int iflag = 0;                  /* run interactively? */
  46: 
  47: main(argc,argv)
  48: int argc;
  49: char **argv;
  50: 
  51: {
  52:     int i;              /* for loop index */
  53:     int userid;         /* uid of owner of file */
  54:     int isuname;            /* is a command line argv a user name?*/
  55:     int numjobs;            /* # of jobs in spooling area */
  56:     int usage();            /* print usage info and exit */
  57:     int allflag = 0;        /* remove all jobs belonging to user? */
  58:     int jobexists;          /* does a requested job exist? */
  59:     int alphasort();        /* sort jobs by date of execution */
  60:     int filewanted();       /* should a file be listed in queue? */
  61:     char *getname();        /* get a user name from a uid */
  62:     struct stat *statptr;       /* pointer to file stat structure */
  63:     struct stat *stbuf[MAXENTRIES]; /* array of pointers to stat structs */
  64:     struct direct **namelist;   /* names of jobs in spooling area */
  65: 
  66: 
  67:     /*
  68: 	 * If job number, user name, or "-" is not specified, just print
  69: 	 * usage info and exit.
  70: 	 */
  71:     if (argc < 2)
  72:         usage();
  73: 
  74:     --argc; ++argv;
  75: 
  76:     /*
  77: 	 * Process command line flags.
  78: 	 * Special case the "-" option so that others may be grouped.
  79: 	 */
  80:     while (argc > 0 && **argv == '-') {
  81:         if (*(++(*argv)) == '\0') {
  82:             ++allflag;
  83:         } else while (**argv) switch (*(*argv)++) {
  84: 
  85:             case 'f':   ++fflag;
  86:                     break;
  87: 
  88:             case 'i':   ++iflag;
  89:                     break;
  90: 
  91:             default:    usage();
  92:         }
  93:         ++argv; --argc;
  94:     }
  95: 
  96:     /*
  97: 	 * If all jobs are to be removed and extra command line arguments
  98: 	 * are given, print usage info and exit.
  99: 	 */
 100:     if (allflag && argc)
 101:         usage();
 102: 
 103:     /*
 104: 	 * If only certain jobs are to be removed and no job #'s or user
 105: 	 * names are specified, print usage info and exit.
 106: 	 */
 107:     if (!allflag && !argc)
 108:         usage();
 109: 
 110:     /*
 111: 	 * If interactive removal and quiet removal are requested, override
 112: 	 * quiet removal and run interactively.
 113: 	 */
 114:     if (iflag && fflag)
 115:         fflag = 0;
 116: 
 117:     /*
 118: 	 * Move to spooling area and get user id of person requesting removal.
 119: 	 */
 120:     if (chdir(ATDIR) == -1) {
 121:         perror(ATDIR);
 122:         exit(1);
 123:     }
 124:     user = getuid();
 125: 
 126:     /*
 127: 	 * Get a list of the files in the spooling area.
 128: 	 */
 129:     if ((numjobs = scandir(".",&namelist,filewanted,alphasort)) < 0) {
 130:         perror(ATDIR);
 131:         exit(1);
 132:     }
 133: 
 134:     /*
 135: 	 * Build an array of pointers to the file stats for all jobs in
 136: 	 * the spooling area.
 137: 	 */
 138:     for (i = 0; i < numjobs; ++i) {
 139:         statptr = (struct stat *) malloc(sizeof(struct stat));
 140:         if (statptr == NULL) {
 141:             perror("malloc");
 142:             exit(1);
 143:         }
 144:         if (stat(namelist[i]->d_name,statptr) < 0) {
 145:             perror("stat");
 146:             continue;
 147:         }
 148:         stbuf[i] = statptr;
 149:     }
 150: 
 151:     /*
 152: 	 * If all jobs belonging to the user are to be removed, compare
 153: 	 * the user's id to the owner of the file. If they match, remove
 154: 	 * the file. If the user is the super-user, don't bother comparing
 155: 	 * the id's. After all files are removed, exit (status 0).
 156: 	 */
 157:     if (allflag) {
 158:         for (i = 0; i < numjobs; ++i) {
 159:             if (user == SUPERUSER || isowner(getname(user),
 160:                             namelist[i]->d_name))
 161:                 (void) removentry(namelist[i]->d_name,
 162:                         (int)stbuf[i]->st_ino,
 163:                             user);
 164:         }
 165:         exit(0);
 166:     }
 167: 
 168:     /*
 169: 	 * If only certain jobs are to be removed, interpret each command
 170: 	 * line argument. A check is done to see if it is a user's name or
 171: 	 * a job number (inode #). If it's a user's name, compare the argument
 172: 	 * to the files owner. If it's a job number, compare the argument to
 173: 	 * the inode number of the file. In either case, if a match occurs,
 174: 	 * try to remove the file. (The function "isusername" scans the
 175: 	 * argument to see if it is all digits which we will assume means
 176: 	 * that it's a job number (a fairly safe assumption?). This is done
 177: 	 * because we have to determine whether we are dealing with a user
 178: 	 * name or a job number. By assuming that only arguments that are
 179: 	 * all digits is a job number, we allow users to have digits in
 180: 	 * their login name i.e. "johndoe2").
 181: 	 */
 182: 
 183:     while (argc--) {
 184:         jobexists = 0;
 185:         isuname = isusername(*argv);
 186:         for (i = 0; i < numjobs; ++i) {
 187: 
 188:             /* if the inode number is 0, this entry was removed */
 189:             if (stbuf[i]->st_ino == 0)
 190:                 continue;
 191: 
 192:             /*
 193: 			 * if argv is a username, compare his/her uid to
 194: 			 * the uid of the owner of the file......
 195: 			 */
 196:             if (isuname) {
 197:                 if (!isowner(*argv,namelist[i]->d_name))
 198:                     continue;
 199: 
 200:             /*
 201: 			 * otherwise, we assume that the argv is a job # and
 202: 			 * thus compare argv to the inode (job #) of the file.
 203: 			 */
 204:             } else {
 205:                 if (stbuf[i]->st_ino != atoi(*argv))
 206:                     continue;
 207:             }
 208:             ++jobexists;
 209:             /*
 210: 			 * if the entry is ultimately removed, don't
 211: 			 * try to remove it again later.
 212: 			 */
 213:             if (removentry(namelist[i]->d_name,
 214:                 (int)stbuf[i]->st_ino, user)) {
 215:                 stbuf[i]->st_ino = 0;
 216:             }
 217:         }
 218: 
 219:         /*
 220: 		 * If a requested argument doesn't exist, print a message.
 221: 		 */
 222:         if (!jobexists && !fflag && !isuname) {
 223:             fprintf(stderr, "%6s: no such job number\n", *argv);
 224:         }
 225:         ++argv;
 226:     }
 227:     exit(0);
 228: }
 229: 
 230: /*
 231:  * Print usage info and exit.
 232:  */
 233: usage()
 234: {
 235:     fprintf(stderr,"usage: atrm [-f] [-i] [-] [[job #] [user] ...]\n");
 236:     exit(1);
 237: }
 238: 
 239: /*
 240:  * Do we want to include a file in the queue? (used by "scandir") We are looking
 241:  * for files with following syntax: yy.ddd.hhhh. so the test is made to see if
 242:  * the file name has three dots in it. This test will suffice since the only
 243:  * other files in /usr/spool/at don't have any dots in their name.
 244:  */
 245: filewanted(direntry)
 246: struct direct *direntry;
 247: {
 248:     int numdot = 0;         /* number of dots in a filename */
 249:     char *filename;         /* filename we are looking at */
 250: 
 251:     filename = direntry->d_name;
 252:     while (*filename)
 253:         numdot += (*(filename++) == '.');
 254:     return(numdot == 3);
 255: }
 256: 
 257: /*
 258:  * Is a command line argument a username? As noted above we will assume
 259:  * that an argument that is all digits means that it's a job number, not
 260:  * a user's name. We choose to determine whether an argument is a user name
 261:  * in this manner because then it's ok for someone to have digits in their
 262:  * user name.
 263:  */
 264: isusername(string)
 265: char *string;
 266: {
 267:     char *ptr;          /* pointer used for scanning string */
 268: 
 269:     ptr = string;
 270:     while (isdigit(*ptr))
 271:         ++ptr;
 272:     return((*ptr == '\0') ? 0 : 1);
 273: }
 274: 
 275: /*
 276:  * Remove an entry from the queue. The access of the file is checked for
 277:  * write permission (since all jobs are mode 644). If access is granted,
 278:  * unlink the file. If the fflag (suppress announcements) is not set,
 279:  * print the job number that we are removing and the result of the access
 280:  * check (either "permission denied" or "removed"). If we are running
 281:  * interactively (iflag), prompt the user before we unlink the file. If
 282:  * the super-user is removing jobs, inform him/her who owns each file before
 283:  * it is removed.  Return TRUE if file removed, else FALSE.
 284:  */
 285: int
 286: removentry(filename,inode,user)
 287: char *filename;
 288: int inode;
 289: int user;
 290: {
 291: 
 292:     if (!fflag)
 293:         printf("%6d: ",inode);
 294: 
 295:     if (!isowner(getname(user),filename) && user != SUPERUSER) {
 296: 
 297:         if (!fflag) {
 298:             printf("permission denied\n");
 299:         }
 300:         return (0);
 301: 
 302:     } else {
 303:         if (iflag) {
 304:             if (user == SUPERUSER) {
 305:                 printf("\t(owned by ");
 306:                 powner(filename);
 307:                 printf(") ");
 308:             }
 309:             printf("remove it? ");
 310:             if (!yes())
 311:                 return (0);
 312:         }
 313:         if (unlink(filename) < 0) {
 314:             if (!fflag) {
 315:                 fputs("could not remove\n", stdout);
 316:                 perror(filename);
 317:             }
 318:             return (0);
 319:         }
 320:         if (!fflag && !iflag)
 321:             printf("removed\n");
 322:         return (1);
 323:     }
 324: }
 325: 
 326: /*
 327:  * See if "name" owns "job".
 328:  */
 329: isowner(name,job)
 330: char *name;
 331: char *job;
 332: {
 333:     char buf[128];          /* buffer for 1st line of spoolfile
 334: 					   header */
 335:     FILE *infile;           /* I/O stream to spoolfile */
 336: 
 337:     if ((infile = fopen(job,"r")) == NULL) {
 338:         fprintf(stderr,"Couldn't open spoolfile ");
 339:         perror(job);
 340:         return(0);
 341:     }
 342: 
 343:     if (fscanf(infile,"# owner: %127s%*[^\n]\n",buf) != 1) {
 344:         fclose(infile);
 345:         return(0);
 346:     }
 347: 
 348:     fclose(infile);
 349:     return((strcmp(name,buf) == 0) ? 1 : 0);
 350: }
 351: 
 352: /*
 353:  * Print the owner of the job. This is stored on the first line of the
 354:  * spoolfile. If we run into trouble getting the name, we'll just print "???".
 355:  */
 356: powner(file)
 357: char *file;
 358: {
 359:     char owner[128];            /* the owner */
 360:     FILE *infile;               /* I/O stream to spoolfile */
 361: 
 362:     /*
 363: 	 * Open the job file and grab the first line.
 364: 	 */
 365: 
 366:     if ((infile = fopen(file,"r")) == NULL) {
 367:         printf("%s","???");
 368:         perror(file);
 369:         return;
 370:     }
 371: 
 372:     if (fscanf(infile,"# owner: %127s%*[^\n]\n",owner) != 1) {
 373:         printf("%s","???");
 374:         fclose(infile);
 375:         return;
 376:     }
 377: 
 378:     fclose(infile);
 379:     printf("%s",owner);
 380: 
 381: }
 382: 
 383: /*
 384:  * Get answer to interactive prompts, eating all characters beyond the first
 385:  * one. If a 'y' is typed, return 1.
 386:  */
 387: yes()
 388: {
 389:     char ch;                /* dummy variable */
 390:     char ch1;               /* dummy variable */
 391: 
 392:     ch = ch1 = getchar();
 393:     while (ch1 != '\n' && ch1 != EOF)
 394:         ch1 = getchar();
 395:     if (isupper(ch))
 396:         ch = tolower(ch);
 397:     return(ch == 'y');
 398: }
 399: 
 400: /*
 401:  * Get the uid of a person using his/her login name. Return -1 if no
 402:  * such account name exists.
 403:  */
 404: getid(name)
 405: char *name;
 406: {
 407: 
 408:     struct passwd *pwdinfo;     /* password info structure */
 409: 
 410:     if ((pwdinfo = getpwnam(name)) == 0)
 411:         return(-1);
 412: 
 413:     return(pwdinfo->pw_uid);
 414: }
 415: 
 416: /*
 417:  * Get the full login name of a person using his/her user id.
 418:  */
 419: char *
 420: getname(uid)
 421: int uid;
 422: {
 423:     struct passwd *pwdinfo;         /* password info structure */
 424: 
 425: 
 426:     if ((pwdinfo = getpwuid(uid)) == 0)
 427:         return("???");
 428:     return(pwdinfo->pw_name);
 429: }

Defined functions

filewanted defined in line 245; used 2 times
getid defined in line 404; never used
getname defined in line 419; used 3 times
isowner defined in line 329; used 3 times
isusername defined in line 264; used 1 times
main defined in line 47; never used
powner defined in line 356; used 1 times
removentry defined in line 285; used 2 times
usage defined in line 233; used 5 times
yes defined in line 387; used 1 times

Defined variables

copyright defined in line 8; never used
fflag defined in line 44; used 8 times
iflag defined in line 45; used 4 times
sccsid defined in line 14; never used
user defined in line 43; used 10 times

Defined macros

ATDIR defined in line 40; used 3 times
MAXENTRIES defined in line 39; used 1 times
  • in line 63
SUPERUSER defined in line 38; used 3 times
Last modified: 1986-05-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1547
Valid CSS Valid XHTML 1.0 Strict