# 2.11BSD#431 - /usr/src/usr.bin/at/atrm.c

##### Functions

    filewanted        X
    getid             X
    getname           X
    isowner           X
    isusername        X
    main              X
    powner            X
    removentry        X
    usage             X
    yes               X

##### Variables

    copyright         X
    fflag             X
    iflag             X
    user              X

##### Macros

    ATDIR             X
    MAXENTRIES        X
    SUPERUSER         X

       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

- in line 60, 129

getid defined in line 404; never used
getname defined in line 419; used 3 times

- in line 61, 159, 295

isowner defined in line 329; used 3 times

- in line 159, 197, 295

isusername defined in line 264; used 1 times

- in line 185

main defined in line 47; never used
powner defined in line 356; used 1 times

- in line 306

removentry defined in line 285; used 2 times

- in line 161, 213

usage defined in line 233; used 5 times

- in line 56, 72, 91, 101, 108

yes defined in line 387; used 1 times

- in line 310

#### Defined variables

copyright defined in line 8; never used
fflag defined in line 44; used 8 times

- in line 85, 114-115(2), 222, 292-297(2), 314, 320

iflag defined in line 45; used 4 times

- in line 88, 114, 303, 320

sccsid defined in line 14; never used
user defined in line 43; used 10 times

- in line 124, 159-163(3), 214, 286-289(2), 295(2), 304

#### Defined macros

ATDIR defined in line 40; used 3 times

- in line 120-121(2), 130

MAXENTRIES defined in line 39; used 1 times

- in line 63

SUPERUSER defined in line 38; used 3 times

- in line 159, 295, 304

Last modified: 1987-02-17 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1919 |