Annotation of 43BSDTahoe/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.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.