|
|
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.