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

unix.superglobalmegacorp.com

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