Annotation of 43BSDReno/usr.bin/at/atrm/atrm.c, revision 1.1.1.1

1.1       root        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.5 (Berkeley) 5/11/89";
                     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 <sys/types.h>
                     31: #include <sys/dir.h>
                     32: #include <sys/file.h>
                     33: #include <sys/stat.h>
                     34: #include <stdio.h>
                     35: #include <pwd.h>
                     36: #include <ctype.h>
                     37: #include "pathnames.h"
                     38: 
                     39: #define SUPERUSER      0                       /* is user super-user? */
                     40: #define MAXENTRIES     1000                    /* max # of entries allowed */
                     41: 
                     42: int user;                                      /* person requesting removal */
                     43: int fflag = 0;                                 /* suppress announcements? */
                     44: int iflag = 0;                                 /* run interactively? */
                     45: 
                     46: main(argc,argv)
                     47: int argc;
                     48: char **argv;
                     49: 
                     50: {
                     51:        register int i;                 /* for loop index */
                     52:        int isuname;                    /* is a command line argv a user name?*/
                     53:        int numjobs;                    /* # of jobs in spooling area */
                     54:        int usage();                    /* print usage info and exit */
                     55:        int allflag = 0;                /* remove all jobs belonging to user? */
                     56:        int jobno;
                     57:        int jobexists;                  /* does a requested job exist? */
                     58:        int alphasort();                /* sort jobs by date of execution */
                     59:        int filewanted();               /* should a file be listed in queue? */
                     60:        char *myname, *getname();       /* current user's name */
                     61:        char *owner, *fowner();
                     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(_PATH_ATDIR) == -1) {
                    121:                perror(_PATH_ATDIR);
                    122:                exit(1);
                    123:        }
                    124:        user = getuid();
                    125:        myname = getname(user);
                    126: 
                    127:        /*
                    128:         * Get a list of the files in the spooling area.
                    129:         */
                    130:        if ((numjobs = scandir(".",&namelist,filewanted,alphasort)) < 0) {
                    131:                perror(_PATH_ATDIR);
                    132:                exit(1);
                    133:        }
                    134: 
                    135:        /*
                    136:         * Build an array of pointers to the file stats for all jobs in
                    137:         * the spooling area.
                    138:         */
                    139:        for (i = 0; i < numjobs; ++i) { 
                    140:                statptr = (struct stat *) malloc(sizeof(struct stat));
                    141:                if (statptr == NULL) {
                    142:                        perror("malloc");
                    143:                        exit(1);
                    144:                }
                    145:                if (stat(namelist[i]->d_name,statptr) < 0) {
                    146:                        perror("stat");
                    147:                        continue;
                    148:                }
                    149:                stbuf[i] = statptr;
                    150:        }
                    151: 
                    152:        /*
                    153:         * If all jobs belonging to the user are to be removed, compare
                    154:         * the user's id to the owner of the file. If they match, remove
                    155:         * the file. If the user is the super-user, don't bother comparing
                    156:         * the id's. After all files are removed, exit (status 0).
                    157:         */
                    158:        if (allflag) {
                    159:                for (i = 0; i < numjobs; ++i) { 
                    160:                        owner = fowner(namelist[i]->d_name); 
                    161:                        if (isowner(myname, owner)) 
                    162:                                removentry(namelist[i]->d_name,
                    163:                                    (int)stbuf[i]->st_ino, NULL);
                    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:                if (!isuname)
                    187:                        jobno = atoi(*argv);
                    188:                for (i = 0; i < numjobs; ++i) {
                    189: 
                    190:                        /* if the inode number is 0, this entry was removed */
                    191:                        if (stbuf[i]->st_ino == 0)
                    192:                                continue;
                    193: 
                    194:                        owner = fowner(namelist[i]->d_name);
                    195:                        /* 
                    196:                         * if argv is a username, compare it to
                    197:                         * the owner of the file......
                    198:                         * otherwise, we assume that the argv is a job # and
                    199:                         * thus compare argv to the inode (job #) of the file.
                    200:                         */
                    201:                        if (isuname) {
                    202:                                if (strcmp(*argv, owner))
                    203:                                        continue;
                    204:                        } else {
                    205:                                if (stbuf[i]->st_ino != jobno) 
                    206:                                        continue;
                    207:                        }
                    208:                        ++jobexists;
                    209:                        /*
                    210:                         * if the entry is removed, don't
                    211:                         * try to remove it again later.
                    212:                         */
                    213:                        if (user == SUPERUSER || isowner(myname, owner)) {
                    214:                                removentry(namelist[i]->d_name,
                    215:                                    (int)stbuf[i]->st_ino, owner);
                    216:                                stbuf[i]->st_ino = 0;
                    217:                        } else if (!fflag)
                    218:                                printf("%6d: permission denied\n",
                    219:                                    stbuf[i]->st_ino);
                    220:                        if (!isuname)
                    221:                                break;
                    222:                }
                    223: 
                    224:                /*
                    225:                 * If a requested argument doesn't exist, print a message.
                    226:                 */
                    227:                if (!jobexists && !fflag && !isuname) {
                    228:                        fprintf(stderr, "%6s: no such job number\n", *argv);
                    229:                }
                    230:                ++argv;
                    231:        }
                    232:        exit(0);
                    233: }
                    234: 
                    235: /*
                    236:  * Print usage info and exit.
                    237:  */
                    238: usage()
                    239: {
                    240:        fprintf(stderr,"usage: atrm [-f] [-i] [-] [[job #] [user] ...]\n");
                    241:        exit(1);
                    242: }
                    243: 
                    244: /*
                    245:  * Do we want to include a file in the queue? (used by "scandir") We are looking
                    246:  * for files with following syntax: yy.ddd.hhhh. so the test is made to see if 
                    247:  * the file name has three dots in it. This test will suffice since the only
                    248:  * other files in /usr/spool/at don't have any dots in their name.
                    249:  */
                    250: filewanted(direntry)
                    251: struct direct *direntry;
                    252: {
                    253:        int numdot = 0;                 /* number of dots in a filename */
                    254:        char *filename;                 /* filename we are looking at */
                    255: 
                    256:        filename = direntry->d_name;
                    257:        while (*filename)
                    258:                numdot += (*(filename++) == '.');
                    259:        return(numdot == 3);
                    260: }
                    261: 
                    262: /*
                    263:  * Is a command line argument a username? As noted above we will assume 
                    264:  * that an argument that is all digits means that it's a job number, not
                    265:  * a user's name. We choose to determine whether an argument is a user name
                    266:  * in this manner because then it's ok for someone to have digits in their 
                    267:  * user name.
                    268:  */
                    269: isusername(string)
                    270: char *string;
                    271: {
                    272:        char *ptr;                      /* pointer used for scanning string */
                    273: 
                    274:        ptr = string;
                    275:        while (isdigit(*ptr))
                    276:                ++ptr;
                    277:        return((*ptr == '\0') ? 0 : 1);
                    278: }
                    279: 
                    280: /*
                    281:  * Remove an entry from the queue. The access of the file is checked for
                    282:  * write permission (since all jobs are mode 644). If access is granted,
                    283:  * unlink the file. If the fflag (suppress announcements) is not set,
                    284:  * print the job number that we are removing and the result of the access
                    285:  * check (either "permission denied" or "removed"). If we are running 
                    286:  * interactively (iflag), prompt the user before we unlink the file. If 
                    287:  * the super-user is removing jobs, inform him/her who owns each file before 
                    288:  * it is removed.
                    289:  */
                    290: removentry(filename, inode, owner)
                    291: char *filename;
                    292: int inode;
                    293: char *owner;
                    294: {
                    295: 
                    296:        if (!fflag)
                    297:                printf("%6d: ",inode);
                    298: 
                    299:        if (iflag) {
                    300:                if (user == SUPERUSER && owner)
                    301:                        printf("\t(owned by %s) ", owner);
                    302:                printf("remove? ");
                    303:                if (!yes())
                    304:                        return;
                    305:        }
                    306:        if (unlink(filename) < 0)
                    307:                perror(filename);
                    308:        else if (!fflag && !iflag)
                    309:                printf("removed\n");
                    310: }
                    311: 
                    312: /*
                    313:  * See if "name" owns job owned by "jobname".
                    314:  */
                    315: isowner(name,jobname)
                    316: char *name;
                    317: char *jobname;
                    318: {
                    319: 
                    320:        return (strcmp(name,jobname) == 0);
                    321: }
                    322: 
                    323: /*
                    324:  * Return the owner of the job. This is stored on the first line of the
                    325:  * spoolfile. If we run into trouble getting the name, we'll just return "???".
                    326:  */
                    327: char *
                    328: fowner(file)
                    329: char *file;
                    330: {
                    331:        static char owner[128];                 /* the owner */
                    332:        FILE *infile;                           /* I/O stream to spoolfile */
                    333: 
                    334:        /*
                    335:         * Open the job file and grab the first line.
                    336:         */
                    337: 
                    338:        if ((infile = fopen(file,"r")) == NULL) {
                    339:                perror(file);
                    340:                return ("???");
                    341:        }
                    342: 
                    343:        if (fscanf(infile,"# owner: %127s%*[^\n]\n",owner) != 1) {
                    344:                fclose(infile);
                    345:                return ("???");
                    346:        }
                    347: 
                    348:        fclose(infile);
                    349:        return (owner);
                    350: 
                    351: }
                    352: 
                    353: /*
                    354:  * Get answer to interactive prompts, eating all characters beyond the first
                    355:  * one. If a 'y' is typed, return 1.
                    356:  */
                    357: yes()
                    358: {
                    359:        char ch;                                /* dummy variable */
                    360:        char ch1;                               /* dummy variable */
                    361: 
                    362:        ch = ch1 = getchar();
                    363:        while (ch1 != '\n' && ch1 != EOF)
                    364:                ch1 = getchar();
                    365:        if (isupper(ch))
                    366:                ch = tolower(ch);
                    367:        return(ch == 'y');
                    368: }
                    369: 
                    370: /*
                    371:  * Get the uid of a person using his/her login name. Return -1 if no
                    372:  * such account name exists.
                    373:  */
                    374: getid(name)
                    375: char *name;
                    376: {
                    377: 
                    378:        struct passwd *pwdinfo;         /* password info structure */
                    379:        
                    380:        if ((pwdinfo = getpwnam(name)) == 0)
                    381:                return(-1);
                    382: 
                    383:        return(pwdinfo->pw_uid);
                    384: }
                    385: 
                    386: /*
                    387:  * Get the full login name of a person using his/her user id.
                    388:  */
                    389: char *
                    390: getname(uid)
                    391: int uid;
                    392: {
                    393:        struct passwd *pwdinfo;                 /* password info structure */
                    394:        char *logname, *getlogin();
                    395:        
                    396: 
                    397:        logname = getlogin();
                    398:        if (logname == NULL || (pwdinfo = getpwnam(logname)) == NULL ||
                    399:            pwdinfo->pw_uid != uid)
                    400:                pwdinfo = getpwuid(uid);
                    401:        if (pwdinfo == 0) {
                    402:                fprintf(stderr, "no name for uid %d?\n", uid);
                    403:                exit(1);
                    404:        }
                    405:        return(pwdinfo->pw_name);
                    406: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.