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