Annotation of 43BSD/usr.bin/at/atrm.c, revision 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.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: }
        !           430: 

unix.superglobalmegacorp.com

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