Annotation of 43BSD/usr.bin/at/atq.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[] = "@(#)atq.c      5.2 (Berkeley) 5/28/86";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  *
                     19:  *     Synopsis:  atq [ -c ] [ -n ] [ name ... ]
                     20:  *
                     21:  *
                     22:  *     Print the queue of files waiting to be executed. These files 
                     23:  *     were created by using the "at" command and are located in the 
                     24:  *     directory "/usr/spool/at".
                     25:  *
                     26:  *
                     27:  *     Author: Steve Wall
                     28:  *             Computer Systems Research Group
                     29:  *             University of California @ Berkeley
                     30:  *
                     31:  */
                     32: 
                     33: # include <stdio.h>
                     34: # include <sys/types.h>
                     35: # include <sys/file.h>
                     36: # include <sys/dir.h>
                     37: # include <sys/stat.h>
                     38: # include <sys/time.h>
                     39: # include <pwd.h>
                     40: # include <ctype.h>
                     41:  
                     42: # define ATDIR         "/usr/spool/at"                 /* spooling area */
                     43: # define LASTFILE      "/usr/spool/at/lasttimedone"    /* update time record 
                     44:                                                           file */
                     45: 
                     46: /*
                     47:  * Months of the year
                     48:  */
                     49: static char *mthnames[12] = {
                     50:        "Jan","Feb","Mar","Apr","May","Jun","Jul",
                     51:        "Aug","Sep","Oct","Nov","Dec",
                     52: };
                     53: 
                     54: char *nullentry = NULL;                        /* avoid 'namelist' NULL ptr problems */
                     55: int numentries;                                /* number of entries in spooling area */
                     56: int namewanted = 0;                    /* only print jobs belonging to a 
                     57:                                           certain person */
                     58: struct direct **queue;                 /* the queue itself */
                     59: 
                     60: 
                     61: main(argc,argv)
                     62: int argc;
                     63: char **argv;
                     64: {
                     65: 
                     66:        int cflag = 0;                  /* print in order of creation time */
                     67:        int nflag = 0;                  /* just print the number of jobs in 
                     68:                                           queue */
                     69:        int usage();                    /* print usage info and exit */
                     70:        int creation();                 /* sort jobs by date of creation */
                     71:        int alphasort();                /* sort jobs by date of execution */
                     72:        int filewanted();               /* should a file be included in queue?*/
                     73:        int printqueue();               /* print the queue */
                     74:        int countfiles();               /* count the number of files in queue
                     75:                                           for a given person */
                     76:        char **namelist = &nullentry;   /* array of specific name(s) requested*/
                     77: 
                     78: 
                     79:        --argc, ++argv;
                     80: 
                     81:        /*
                     82:         * Interpret command line flags if they exist.
                     83:         */
                     84:        while (argc > 0 && **argv == '-') {
                     85:                (*argv)++;
                     86:                while (**argv) switch (*(*argv)++) {
                     87: 
                     88:                        case 'c' :      cflag++; 
                     89:                                        break;
                     90: 
                     91:                        case 'n' :      nflag++; 
                     92:                                        break;
                     93: 
                     94:                        default  :      usage();
                     95: 
                     96:                }
                     97:                --argc, ++argv;
                     98:        }
                     99: 
                    100:        /*
                    101:         * If a certain name (or names) is requested, set a pointer to the
                    102:         * beginning of the list.
                    103:         */
                    104:        if (argc > 0) {
                    105:                ++namewanted;
                    106:                namelist = argv;
                    107:        }
                    108: 
                    109:        /*
                    110:         * Move to the spooling area and scan the directory, placing the
                    111:         * files in the queue structure. The queue comes back sorted by
                    112:         * execution time or creation time.
                    113:         */
                    114:        if (chdir(ATDIR) == -1) {
                    115:                perror(ATDIR);
                    116:                exit(1);
                    117:        }
                    118:        if ((numentries = scandir(".",&queue,filewanted, (cflag) ? creation : 
                    119:                                alphasort)) < 0) {
                    120:                perror(ATDIR);
                    121:                exit(1);
                    122:        }
                    123: 
                    124:        /*
                    125:         * Either print a message stating:
                    126:         *
                    127:         *      1) that the spooling area is empty.
                    128:         *      2) the number of jobs in the spooling area.
                    129:         *      3) the number of jobs in the spooling area belonging to 
                    130:         *         a certain person.
                    131:         *      4) that the person requested doesn't have any files in the
                    132:         *         spooling area.
                    133:         *
                    134:         * or send the queue off to "printqueue" for printing.
                    135:         *
                    136:         * This whole process might seem a bit elaborate, but it's worthwhile
                    137:         * to print some informative messages for the user.
                    138:         *
                    139:         */
                    140:        if ((numentries == 0) && (!nflag)) {
                    141:                printf("no files in queue.\n");
                    142:                exit(0);
                    143:        }
                    144:        if (nflag) {
                    145:                printf("%d\n",(namewanted) ? countfiles(namelist) : numentries);
                    146:                exit(0);
                    147:        }
                    148:        if ((namewanted) && (countfiles(namelist) == 0)) {
                    149:                printf("no files for %s.\n", (argc == 1) ?
                    150:                                        *argv : "specified users");
                    151:                exit(0);
                    152:        }
                    153:        printqueue(namelist);
                    154:        exit(0);
                    155: }
                    156: 
                    157: /*
                    158:  * Count the number of jobs in the spooling area owned by a certain person(s).
                    159:  */
                    160: countfiles(namelist)
                    161: char **namelist;
                    162: {
                    163:        int i;                                  /* for loop index */
                    164:        int entryfound;                         /* found file owned by user(s)*/
                    165:        int numfiles = 0;                       /* number of files owned by a
                    166:                                                   certain person(s) */
                    167:        char **ptr;                             /* scratch pointer */
                    168: 
                    169: 
                    170:        /*
                    171:         * For each file in the queue, see if the user(s) own the file. We
                    172:         * have to use "entryfound" (rather than simply incrementing "numfiles")
                    173:         * so that if a person's name appears twice on the command line we 
                    174:         * don't double the number of files owned by him/her.
                    175:         */
                    176:        for (i = 0; i < numentries ; i++) {
                    177:                ptr = namelist;
                    178:                entryfound = 0;
                    179: 
                    180:                while (*ptr) {
                    181:                        if (isowner(*ptr,queue[i]->d_name))
                    182:                                ++entryfound;
                    183:                        ++ptr;
                    184:                }
                    185:                if (entryfound)
                    186:                        ++numfiles;
                    187:        }
                    188:        return(numfiles);
                    189: }
                    190: 
                    191: /*
                    192:  * Print the queue. If only jobs belonging to a certain person(s) are requested,
                    193:  * only print jobs that belong to that person(s).
                    194:  */
                    195: printqueue(namelist)
                    196: char **namelist;
                    197: {
                    198:        int i;                                  /* for loop index */
                    199:        int rank = 1;                           /* rank of a job */
                    200:        int entryfound;                         /* found file owned by user(s)*/
                    201:        int printrank();                        /* print the rank of a job */
                    202:        int plastrun();                         /* print the last time the 
                    203:                                                   spooling area was updated */
                    204:        int powner();                           /* print the name of the owner
                    205:                                                   of the job */
                    206:        int getid();                            /* get uid of a person */
                    207:        char **ptr;                             /* scratch pointer */
                    208:        struct stat stbuf;                      /* buffer for file stats */
                    209: 
                    210: 
                    211:        /*
                    212:         * Print the time the spooling area was last modified and the header
                    213:         * for the queue.
                    214:         */
                    215:        plastrun();
                    216:        printf(" Rank     Execution Date     Owner     Job #   Job Name\n");
                    217: 
                    218:        /*
                    219:         * Print the queue. If a certain name(s) was requested, print only jobs
                    220:         * belonging to that person(s), otherwise print the entire queue.
                    221:         * Once again, we have to use "entryfound" (rather than simply 
                    222:         * comparing each command line argument) so that if a person's name 
                    223:         * appears twice we don't print each file owned by him/her twice.
                    224:         *
                    225:         *
                    226:         * "printrank", "printdate", and "printjobname" all take existing 
                    227:         * data and display it in a friendly manner.
                    228:         *
                    229:         */
                    230:        for (i = 0; i < numentries; i++) {
                    231:                if ((stat(queue[i]->d_name, &stbuf)) < 0) {
                    232:                        continue;
                    233:                }
                    234:                if (namewanted) {
                    235:                        ptr = namelist;
                    236:                        entryfound = 0;
                    237: 
                    238:                        while (*ptr) {
                    239:                                if (isowner(*ptr,queue[i]->d_name))
                    240:                                        ++entryfound;
                    241:                                ++ptr;
                    242:                        }
                    243:                        if (!entryfound)
                    244:                                continue;
                    245:                }
                    246:                printrank(rank++);
                    247:                printdate(queue[i]->d_name);
                    248:                powner(queue[i]->d_name);
                    249:                printf("%5d",stbuf.st_ino);
                    250:                printjobname(queue[i]->d_name);
                    251:        }
                    252:        ++ptr;
                    253: }
                    254: 
                    255: /*
                    256:  * See if "name" owns "job".
                    257:  */
                    258: isowner(name,job)
                    259: char *name;
                    260: char *job;
                    261: {
                    262:        char buf[128];                  /* buffer for 1st line of spoolfile 
                    263:                                           header */
                    264:        FILE *infile;                   /* I/O stream to spoolfile */
                    265: 
                    266:        if ((infile = fopen(job,"r")) == NULL) {
                    267:                fprintf(stderr,"Couldn't open spoolfile ");
                    268:                perror(job);
                    269:                return(0);
                    270:        }
                    271: 
                    272:        if (fscanf(infile,"# owner: %127s%*[^\n]\n",buf) != 1) {
                    273:                fclose(infile);
                    274:                return(0);
                    275:        }
                    276: 
                    277:        fclose(infile);
                    278:        return((strcmp(name,buf) == 0) ? 1 : 0);
                    279: }
                    280: 
                    281: /*
                    282:  * Print the owner of the job. This is stored on the first line of the
                    283:  * spoolfile. If we run into trouble getting the name, we'll just print "???".
                    284:  */
                    285: powner(file)
                    286: char *file;
                    287: {
                    288:        char owner[10];                         /* the owner */
                    289:        FILE *infile;                           /* I/O stream to spoolfile */
                    290: 
                    291:        /*
                    292:         * Open the job file and grab the first line.
                    293:         */
                    294: 
                    295:        if ((infile = fopen(file,"r")) == NULL) {
                    296:                printf("%-10.9s","???");
                    297:                perror(file);
                    298:                return;
                    299:        }
                    300: 
                    301:        if (fscanf(infile,"# owner: %9s%*[^\n]\n",owner) != 1) {
                    302:                printf("%-10.9s","???");
                    303:                fclose(infile);
                    304:                return;
                    305:        }
                    306: 
                    307:        fclose(infile);
                    308:        printf("%-10.9s",owner);
                    309: 
                    310: }
                    311:        
                    312: 
                    313: /*
                    314:  * Get the uid of a person using his/her login name. Return -1 if no
                    315:  * such account name exists.
                    316:  */
                    317: getid(name)
                    318: char *name;
                    319: {
                    320: 
                    321:        struct passwd *pwdinfo;                 /* password info structure */
                    322: 
                    323: 
                    324:        if ((pwdinfo = getpwnam(name)) == 0)
                    325:                return(-1);
                    326: 
                    327:        return(pwdinfo->pw_uid);
                    328: }
                    329: 
                    330: /*
                    331:  * Print the time the spooling area was updated.
                    332:  */
                    333: plastrun()
                    334: {
                    335:        struct timeval now;                     /* time it is right now */
                    336:        struct timezone zone;                   /* NOT USED */
                    337:        struct tm *loc;                         /* detail of time it is right */
                    338:        u_long lasttime;                        /* last update time in seconds
                    339:                                                   since 1/1/70 */
                    340:        FILE *last;                             /* file where last update hour
                    341:                                                   is stored */
                    342: 
                    343: 
                    344:        /*
                    345:         * Open the file where the last update time is stored, and grab the
                    346:         * last update hour. The update time is measured in seconds since
                    347:         * 1/1/70.
                    348:         */
                    349:        if ((last = fopen(LASTFILE,"r")) == NULL) {
                    350:                perror(LASTFILE);
                    351:                exit(1);
                    352:        }
                    353:        fscanf(last,"%d",(u_long) &lasttime);
                    354:        fclose(last);
                    355: 
                    356:        /*
                    357:         * Get a broken down representation of the last update time.
                    358:         */
                    359:        loc = localtime(&lasttime);
                    360: 
                    361:        /*
                    362:         * Print the time that the spooling area was last updated.
                    363:         */
                    364:        printf("\n LAST EXECUTION TIME: %s ",mthnames[loc->tm_mon]);
                    365:        printf("%d, 19%d ",loc->tm_mday,loc->tm_year);
                    366:        printf("at %d:%02d\n\n",loc->tm_hour,loc->tm_min);
                    367: }
                    368: 
                    369: /*
                    370:  * Print the rank of a job. (I've got to admit it, I stole it from "lpq")
                    371:  */
                    372: static 
                    373: printrank(n)
                    374: {
                    375:        static char *r[] = {
                    376:                "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
                    377:        };
                    378: 
                    379:        if ((n/10) == 1)
                    380:                 printf("%3d%-5s", n,"th");
                    381:        else
                    382:                 printf("%3d%-5s", n, r[n%10]);
                    383: }
                    384: 
                    385: /*
                    386:  * Print the date that a job is to be executed. This takes some manipulation 
                    387:  * of the file name.
                    388:  */
                    389: printdate(filename)
                    390: char *filename;
                    391: {
                    392:        int yday  =  0;                         /* day of year file will be 
                    393:                                                   executed */
                    394:        int min   =  0;                         /* min. file will be executed */
                    395:        int hour  =  0;                         /* hour file will be executed */
                    396:        int day   =  0;                         /* day file will be executed */
                    397:        int month =  0;                         /* month file will be executed*/
                    398:        int year  =  0;                         /* year file will be executed */
                    399:        int get_mth_day();                      /* convert a day of year to a
                    400:                                                   month and day of month */
                    401:        char date[18];                          /* reformatted execution date */
                    402: 
                    403:        /*
                    404:         * Pick off the necessary info from the file name and convert the day
                    405:         * of year to a month and day of month.
                    406:         */
                    407:        sscanf(filename,"%2d.%3d.%2d%2d",&year,&yday,&hour,&min);
                    408:        get_mth_day(year,yday,&month,&day);
                    409: 
                    410:        /*
                    411:         * Format the execution date of a job.
                    412:         */
                    413:        sprintf(date,"%3s %2d, 19%2d %02d:%02d",mthnames[month],
                    414:                                                    day, year,hour,min);
                    415: 
                    416:        /*
                    417:         * Print the date the job will be executed.
                    418:         */
                    419:        printf("%-21.18s",date);
                    420: }
                    421: 
                    422: /*
                    423:  * Given a day of the year, calculate the month and day of month.
                    424:  */
                    425: get_mth_day(year,dayofyear,month,day)
                    426: int year, dayofyear, *month, *day;
                    427: 
                    428: {
                    429: 
                    430:        int i = 1;                              /* for loop index */
                    431:        int leap;                               /* are we dealing with a leap
                    432:                                                   year? */
                    433:                                                /* Table of the number of days 
                    434:                                                   in each month of the year.
                    435: 
                    436:                                                     dofy_tab[1] -- regular year
                    437:                                                     dofy_tab[2] -- leap year 
                    438:                                                                              */
                    439: 
                    440:        static int dofy_tab[2][13] = {
                    441:                { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                    442:                { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                    443:        };
                    444: 
                    445:        /*
                    446:         * Are we dealing with a leap year?
                    447:         */
                    448:        leap = ((year%4 == 0 && year%100 != 0) || year%100 == 0);
                    449: 
                    450:        /*
                    451:         * Calculate the month of the year and day of the month.
                    452:         */
                    453:        while (dayofyear >= dofy_tab[leap][i]) {
                    454:                dayofyear -= dofy_tab[leap][i++];
                    455:                ++(*month);
                    456:        }
                    457:        *day = (dayofyear + 1);
                    458: }
                    459:        
                    460: /*
                    461:  * Print a job name. If the old "at" has been used to create the spoolfile,
                    462:  * the three line header that the new version of "at" puts in the spoolfile.
                    463:  * Thus, we just print "???".
                    464:  */
                    465: printjobname(file)
                    466: char *file;
                    467: {
                    468:        char *ptr;                              /* scratch pointer */
                    469:        char jobname[28];                       /* the job name */
                    470:        FILE *filename;                         /* job file in spooling area */
                    471: 
                    472:        /*
                    473:         * Open the job file and grab the second line.
                    474:         */
                    475:        printf("   ");
                    476: 
                    477:        if ((filename = fopen(file,"r")) == NULL) {
                    478:                printf("%.27s\n", "???");
                    479:                perror(file);
                    480:                return;
                    481:        }
                    482:        /*
                    483:         * Skip over the first line.
                    484:         */
                    485:        fscanf(filename,"%*[^\n]\n");
                    486: 
                    487:        /*
                    488:         * Now get the job name.
                    489:         */
                    490:        if (fscanf(filename,"# jobname: %27s%*[^\n]\n",jobname) != 1) {
                    491:                printf("%.27s\n", "???");
                    492:                fclose(filename);
                    493:                return;
                    494:        }
                    495:        fclose(filename);
                    496: 
                    497:        /*
                    498:         * Put a pointer at the begining of the line and remove the basename
                    499:         * from the job file.
                    500:         */
                    501:        ptr = jobname;
                    502:        if ((ptr = (char *)rindex(jobname,'/')) != 0)
                    503:                ++ptr;
                    504:        else 
                    505:                ptr = jobname;
                    506: 
                    507:        if (strlen(ptr) > 23)
                    508:                printf("%.23s ...\n",ptr);
                    509:        else
                    510:                printf("%.27s\n",ptr);
                    511: }
                    512: 
                    513: /*
                    514:  * Do we want to include a file in the queue? (used by "scandir") We are looking
                    515:  * for files with following syntax: yy.ddd.hhhh. so the test is made to see if 
                    516:  * the file name has three dots in it. This test will suffice since the only
                    517:  * other files in /usr/spool/at don't have any dots in their name.
                    518:  */
                    519: filewanted(direntry)
                    520: struct direct *direntry;
                    521: {
                    522:        int numdot = 0;
                    523:        char *filename;
                    524: 
                    525:        filename = direntry->d_name;
                    526:        while (*filename)
                    527:                numdot += (*(filename++) == '.');
                    528:        return(numdot == 3);
                    529: }
                    530: 
                    531: /*
                    532:  * Sort files by time of creation. (used by "scandir")
                    533:  */
                    534: creation(d1, d2)
                    535: struct direct **d1, **d2;
                    536: {
                    537:        struct stat stbuf1, stbuf2;
                    538: 
                    539:        if (stat((*d1)->d_name,&stbuf1) < 0)
                    540:                return(1);
                    541: 
                    542:        if (stat((*d2)->d_name,&stbuf2) < 0)
                    543:                return(1);
                    544: 
                    545:        return(stbuf1.st_ctime < stbuf2.st_ctime);
                    546: }
                    547:        
                    548: /*
                    549:  * Print usage info and exit.
                    550:  */
                    551: usage() 
                    552: {
                    553:        fprintf(stderr,"usage:  atq [-c] [-n] [name ...]\n");
                    554:        exit(1);
                    555: }

unix.superglobalmegacorp.com

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