|
|
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.1 (Berkeley) 6/6/85"; ! 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: ! 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; /* 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 (**argv) { ! 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[30]; /* 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: %s\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[80]; /* 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: return; ! 298: } ! 299: ! 300: if (fscanf(infile,"# owner: %s",owner) != 1) { ! 301: printf("%-10.9s","???"); ! 302: fclose(infile); ! 303: return; ! 304: } ! 305: ! 306: fclose(infile); ! 307: printf("%-10.9s",owner); ! 308: ! 309: } ! 310: ! 311: ! 312: /* ! 313: * Get the uid of a person using his/her login name. Return -1 if no ! 314: * such account name exists. ! 315: */ ! 316: getid(name) ! 317: char *name; ! 318: { ! 319: ! 320: struct passwd *pwdinfo; /* password info structure */ ! 321: ! 322: ! 323: if ((pwdinfo = getpwnam(name)) == 0) ! 324: return(-1); ! 325: ! 326: return(pwdinfo->pw_uid); ! 327: } ! 328: ! 329: /* ! 330: * Print the time the spooling area was updated. ! 331: */ ! 332: plastrun() ! 333: { ! 334: struct timeval now; /* time it is right now */ ! 335: struct timezone zone; /* NOT USED */ ! 336: struct tm *loc; /* detail of time it is right */ ! 337: u_long lasttime; /* last update time in seconds ! 338: since 1/1/70 */ ! 339: FILE *last; /* file where last update hour ! 340: is stored */ ! 341: ! 342: ! 343: /* ! 344: * Open the file where the last update time is stored, and grab the ! 345: * last update hour. The update time is measured in seconds since ! 346: * 1/1/70. ! 347: */ ! 348: if ((last = fopen(LASTFILE,"r")) == NULL) { ! 349: perror(LASTFILE); ! 350: exit(1); ! 351: } ! 352: fscanf(last,"%d",(u_long) &lasttime); ! 353: fclose(last); ! 354: ! 355: /* ! 356: * Get a broken down representation of the last update time. ! 357: */ ! 358: loc = localtime(&lasttime); ! 359: ! 360: /* ! 361: * Print the time that the spooling area was last updated. ! 362: */ ! 363: printf("\n LAST EXECUTION TIME: %s ",mthnames[loc->tm_mon]); ! 364: printf("%d, 19%d ",loc->tm_mday,loc->tm_year); ! 365: printf("at %d:%02d\n\n",loc->tm_hour,loc->tm_min); ! 366: } ! 367: ! 368: /* ! 369: * Print the rank of a job. (I've got to admit it, I stole it from "lpq") ! 370: */ ! 371: static ! 372: printrank(n) ! 373: { ! 374: static char *r[] = { ! 375: "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" ! 376: }; ! 377: ! 378: if ((n/10) == 1) ! 379: printf("%3d%-5s", n,"th"); ! 380: else ! 381: printf("%3d%-5s", n, r[n%10]); ! 382: } ! 383: ! 384: /* ! 385: * Print the date that a job is to be executed. This takes some manipulation ! 386: * of the file name. ! 387: */ ! 388: printdate(filename) ! 389: char *filename; ! 390: { ! 391: int yday = 0; /* day of year file will be ! 392: executed */ ! 393: int min = 0; /* min. file will be executed */ ! 394: int hour = 0; /* hour file will be executed */ ! 395: int day = 0; /* day file will be executed */ ! 396: int month = 0; /* month file will be executed*/ ! 397: int year = 0; /* year file will be executed */ ! 398: int get_mth_day(); /* convert a day of year to a ! 399: month and day of month */ ! 400: char date[18]; /* reformatted execution date */ ! 401: ! 402: /* ! 403: * Pick off the necessary info from the file name and convert the day ! 404: * of year to a month and day of month. ! 405: */ ! 406: sscanf(filename,"%2d.%3d.%2d%2d",&year,&yday,&hour,&min); ! 407: get_mth_day(year,yday,&month,&day); ! 408: ! 409: /* ! 410: * Format the execution date of a job. ! 411: */ ! 412: sprintf(date,"%3s %2d, 19%2d %02d:%02d",mthnames[month], ! 413: day, year,hour,min); ! 414: ! 415: /* ! 416: * Print the date the job will be executed. ! 417: */ ! 418: printf("%-21.18s",date); ! 419: } ! 420: ! 421: /* ! 422: * Given a day of the year, calculate the month and day of month. ! 423: */ ! 424: get_mth_day(year,dayofyear,month,day) ! 425: int year, dayofyear, *month, *day; ! 426: ! 427: { ! 428: ! 429: int i = 1; /* for loop index */ ! 430: int leap; /* are we dealing with a leap ! 431: year? */ ! 432: /* Table of the number of days ! 433: in each month of the year. ! 434: ! 435: dofy_tab[1] -- regular year ! 436: dofy_tab[2] -- leap year ! 437: */ ! 438: ! 439: static int dofy_tab[2][13] = { ! 440: { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, ! 441: { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, ! 442: }; ! 443: ! 444: /* ! 445: * Are we dealing with a leap year? ! 446: */ ! 447: leap = ((year%4 == 0 && year%100 != 0) || year%100 == 0); ! 448: ! 449: /* ! 450: * Calculate the month of the year and day of the month. ! 451: */ ! 452: while (dayofyear >= dofy_tab[leap][i]) { ! 453: dayofyear -= dofy_tab[leap][i++]; ! 454: ++(*month); ! 455: } ! 456: *day = (dayofyear + 1); ! 457: } ! 458: ! 459: /* ! 460: * Print a job name. If the old "at" has been used to create the spoolfile, ! 461: * the three line header that the new version of "at" puts in the spoolfile. ! 462: * Thus, we just print "???". ! 463: */ ! 464: printjobname(file) ! 465: char *file; ! 466: { ! 467: char *ptr; /* scratch pointer */ ! 468: char jobname[80]; /* the job name */ ! 469: FILE *filename; /* job file in spooling area */ ! 470: ! 471: /* ! 472: * Open the job file and grab the second line. ! 473: */ ! 474: printf(" "); ! 475: ! 476: if ((filename = fopen(file,"r")) == NULL) { ! 477: printf("%.27s\n", "???"); ! 478: return; ! 479: } ! 480: /* ! 481: * We'll yank the first line into the buffer temporarily. ! 482: */ ! 483: fgets(jobname,80,filename); ! 484: ! 485: /* ! 486: * Now get the job name. ! 487: */ ! 488: if (fscanf(filename,"# jobname: %s",jobname) != 1) { ! 489: printf("%.27s\n", "???"); ! 490: fclose(filename); ! 491: return; ! 492: } ! 493: fclose(filename); ! 494: ! 495: /* ! 496: * Put a pointer at the begining of the line and remove the basename ! 497: * from the job file. ! 498: */ ! 499: ptr = jobname; ! 500: if ((ptr = (char *)rindex(jobname,'/')) != 0) ! 501: ++ptr; ! 502: else ! 503: ptr = jobname; ! 504: ! 505: if (strlen(ptr) > 23) ! 506: printf("%.23s ...\n",ptr); ! 507: else ! 508: printf("%.27s\n",ptr); ! 509: } ! 510: ! 511: /* ! 512: * Do we want to include a file in the queue? (used by "scandir") We are looking ! 513: * for files with following syntax: yy.ddd.hhhh. so the test is made to see if ! 514: * the file name has three dots in it. This test will suffice since the only ! 515: * other files in /usr/spool/at don't have any dots in their name. ! 516: */ ! 517: filewanted(direntry) ! 518: struct direct *direntry; ! 519: { ! 520: int numdot = 0; ! 521: char *filename; ! 522: ! 523: filename = direntry->d_name; ! 524: while (*filename) ! 525: numdot += (*(filename++) == '.'); ! 526: return(numdot == 3); ! 527: } ! 528: ! 529: /* ! 530: * Sort files by time of creation. (used by "scandir") ! 531: */ ! 532: creation(d1, d2) ! 533: struct direct **d1, **d2; ! 534: { ! 535: struct stat stbuf1, stbuf2; ! 536: ! 537: if (stat((*d1)->d_name,&stbuf1) < 0) ! 538: return(1); ! 539: ! 540: if (stat((*d2)->d_name,&stbuf2) < 0) ! 541: return(1); ! 542: ! 543: return(stbuf1.st_ctime < stbuf2.st_ctime); ! 544: } ! 545: ! 546: /* ! 547: * Print usage info and exit. ! 548: */ ! 549: usage() ! 550: { ! 551: fprintf(stderr,"usage: atq [-c] [-n] [name ...]\n"); ! 552: exit(1); ! 553: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.