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

unix.superglobalmegacorp.com

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