|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.