xref: /original-bsd/usr.bin/at/atq/atq.c (revision c7338628)
1852e9da9Sdist /*
2852e9da9Sdist  * Copyright (c) 1983 Regents of the University of California.
3852e9da9Sdist  * All rights reserved.  The Berkeley software License Agreement
4852e9da9Sdist  * specifies the terms and conditions for redistribution.
5852e9da9Sdist  */
6852e9da9Sdist 
795d7ed8eSwall #ifndef lint
8852e9da9Sdist char copyright[] =
9852e9da9Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10852e9da9Sdist  All rights reserved.\n";
11852e9da9Sdist #endif not lint
12852e9da9Sdist 
13852e9da9Sdist #ifndef lint
14*c7338628Sbostic static char sccsid[] = "@(#)atq.c	5.4 (Berkeley) 04/06/87";
152d68a685Smckusick #endif not lint
1695d7ed8eSwall 
1795d7ed8eSwall /*
1895d7ed8eSwall  *
1995d7ed8eSwall  *	Synopsis:  atq [ -c ] [ -n ] [ name ... ]
2095d7ed8eSwall  *
2195d7ed8eSwall  *
2295d7ed8eSwall  *	Print the queue of files waiting to be executed. These files
2395d7ed8eSwall  *	were created by using the "at" command and are located in the
2495d7ed8eSwall  *	directory "/usr/spool/at".
2595d7ed8eSwall  *
2695d7ed8eSwall  *
2795d7ed8eSwall  *	Author: Steve Wall
2895d7ed8eSwall  *		Computer Systems Research Group
2995d7ed8eSwall  *		University of California @ Berkeley
3095d7ed8eSwall  *
3195d7ed8eSwall  */
3295d7ed8eSwall 
3395d7ed8eSwall # include <stdio.h>
3495d7ed8eSwall # include <sys/types.h>
3595d7ed8eSwall # include <sys/file.h>
3695d7ed8eSwall # include <sys/dir.h>
3795d7ed8eSwall # include <sys/stat.h>
3895d7ed8eSwall # include <sys/time.h>
3995d7ed8eSwall # include <pwd.h>
4095d7ed8eSwall # include <ctype.h>
4195d7ed8eSwall 
4295d7ed8eSwall # define ATDIR		"/usr/spool/at"			/* spooling area */
4395d7ed8eSwall # define LASTFILE	"/usr/spool/at/lasttimedone"	/* update time record
4495d7ed8eSwall 							   file */
4595d7ed8eSwall 
4695d7ed8eSwall /*
4795d7ed8eSwall  * Months of the year
4895d7ed8eSwall  */
4995d7ed8eSwall static char *mthnames[12] = {
5095d7ed8eSwall 	"Jan","Feb","Mar","Apr","May","Jun","Jul",
5195d7ed8eSwall 	"Aug","Sep","Oct","Nov","Dec",
5295d7ed8eSwall };
5395d7ed8eSwall 
541ed914fbSmckusick char *nullentry = NULL;			/* avoid 'namelist' NULL ptr problems */
5595d7ed8eSwall int numentries;				/* number of entries in spooling area */
5695d7ed8eSwall int namewanted = 0;			/* only print jobs belonging to a
5795d7ed8eSwall 					   certain person */
5895d7ed8eSwall struct direct **queue;			/* the queue itself */
5995d7ed8eSwall 
6095d7ed8eSwall 
6195d7ed8eSwall main(argc,argv)
6295d7ed8eSwall int argc;
6395d7ed8eSwall char **argv;
6495d7ed8eSwall {
6595d7ed8eSwall 
6695d7ed8eSwall 	int cflag = 0;			/* print in order of creation time */
6795d7ed8eSwall 	int nflag = 0;			/* just print the number of jobs in
6895d7ed8eSwall 					   queue */
6995d7ed8eSwall 	int usage();			/* print usage info and exit */
7095d7ed8eSwall 	int creation();			/* sort jobs by date of creation */
7195d7ed8eSwall 	int alphasort();		/* sort jobs by date of execution */
7295d7ed8eSwall 	int filewanted();		/* should a file be included in queue?*/
7395d7ed8eSwall 	int printqueue();		/* print the queue */
7495d7ed8eSwall 	int countfiles();		/* count the number of files in queue
7595d7ed8eSwall 					   for a given person */
761ed914fbSmckusick 	char **namelist = &nullentry;	/* array of specific name(s) requested*/
7795d7ed8eSwall 
7895d7ed8eSwall 
7995d7ed8eSwall 	--argc, ++argv;
8095d7ed8eSwall 
8195d7ed8eSwall 	/*
8295d7ed8eSwall 	 * Interpret command line flags if they exist.
8395d7ed8eSwall 	 */
8495d7ed8eSwall 	while (argc > 0 && **argv == '-') {
8595d7ed8eSwall 		(*argv)++;
8695d7ed8eSwall 		while (**argv) switch (*(*argv)++) {
8795d7ed8eSwall 
8895d7ed8eSwall 			case 'c' :	cflag++;
8995d7ed8eSwall 					break;
9095d7ed8eSwall 
9195d7ed8eSwall 			case 'n' :	nflag++;
9295d7ed8eSwall 					break;
9395d7ed8eSwall 
9495d7ed8eSwall 			default	 :	usage();
9595d7ed8eSwall 
9695d7ed8eSwall 		}
9795d7ed8eSwall 		--argc, ++argv;
9895d7ed8eSwall 	}
9995d7ed8eSwall 
10095d7ed8eSwall 	/*
10195d7ed8eSwall 	 * If a certain name (or names) is requested, set a pointer to the
10295d7ed8eSwall 	 * beginning of the list.
10395d7ed8eSwall 	 */
1041ed914fbSmckusick 	if (argc > 0) {
10595d7ed8eSwall 		++namewanted;
10695d7ed8eSwall 		namelist = argv;
10795d7ed8eSwall 	}
10895d7ed8eSwall 
10995d7ed8eSwall 	/*
11095d7ed8eSwall 	 * Move to the spooling area and scan the directory, placing the
11195d7ed8eSwall 	 * files in the queue structure. The queue comes back sorted by
11295d7ed8eSwall 	 * execution time or creation time.
11395d7ed8eSwall 	 */
11495d7ed8eSwall 	if (chdir(ATDIR) == -1) {
11595d7ed8eSwall 		perror(ATDIR);
11695d7ed8eSwall 		exit(1);
11795d7ed8eSwall 	}
11895d7ed8eSwall 	if ((numentries = scandir(".",&queue,filewanted, (cflag) ? creation :
11995d7ed8eSwall 				alphasort)) < 0) {
12095d7ed8eSwall 		perror(ATDIR);
12195d7ed8eSwall 		exit(1);
12295d7ed8eSwall 	}
12395d7ed8eSwall 
12495d7ed8eSwall 	/*
12595d7ed8eSwall 	 * Either print a message stating:
12695d7ed8eSwall 	 *
12795d7ed8eSwall 	 *	1) that the spooling area is empty.
12895d7ed8eSwall 	 *	2) the number of jobs in the spooling area.
12995d7ed8eSwall 	 *	3) the number of jobs in the spooling area belonging to
13095d7ed8eSwall 	 *	   a certain person.
13195d7ed8eSwall 	 *	4) that the person requested doesn't have any files in the
13295d7ed8eSwall 	 *	   spooling area.
13395d7ed8eSwall 	 *
13495d7ed8eSwall 	 * or send the queue off to "printqueue" for printing.
13595d7ed8eSwall 	 *
13695d7ed8eSwall 	 * This whole process might seem a bit elaborate, but it's worthwhile
13795d7ed8eSwall 	 * to print some informative messages for the user.
13895d7ed8eSwall 	 *
13995d7ed8eSwall 	 */
14095d7ed8eSwall 	if ((numentries == 0) && (!nflag)) {
14195d7ed8eSwall 		printf("no files in queue.\n");
14295d7ed8eSwall 		exit(0);
14395d7ed8eSwall 	}
14495d7ed8eSwall 	if (nflag) {
14595d7ed8eSwall 		printf("%d\n",(namewanted) ? countfiles(namelist) : numentries);
14695d7ed8eSwall 		exit(0);
14795d7ed8eSwall 	}
14895d7ed8eSwall 	if ((namewanted) && (countfiles(namelist) == 0)) {
14995d7ed8eSwall 		printf("no files for %s.\n", (argc == 1) ?
15095d7ed8eSwall 					*argv : "specified users");
15195d7ed8eSwall 		exit(0);
15295d7ed8eSwall 	}
15395d7ed8eSwall 	printqueue(namelist);
15495d7ed8eSwall 	exit(0);
15595d7ed8eSwall }
15695d7ed8eSwall 
15795d7ed8eSwall /*
15895d7ed8eSwall  * Count the number of jobs in the spooling area owned by a certain person(s).
15995d7ed8eSwall  */
16095d7ed8eSwall countfiles(namelist)
16195d7ed8eSwall char **namelist;
16295d7ed8eSwall {
16395d7ed8eSwall 	int i;					/* for loop index */
16495d7ed8eSwall 	int entryfound;				/* found file owned by user(s)*/
16595d7ed8eSwall 	int numfiles = 0;			/* number of files owned by a
16695d7ed8eSwall 						   certain person(s) */
16795d7ed8eSwall 	char **ptr;				/* scratch pointer */
16895d7ed8eSwall 
16995d7ed8eSwall 
17095d7ed8eSwall 	/*
17195d7ed8eSwall 	 * For each file in the queue, see if the user(s) own the file. We
17295d7ed8eSwall 	 * have to use "entryfound" (rather than simply incrementing "numfiles")
17395d7ed8eSwall 	 * so that if a person's name appears twice on the command line we
17495d7ed8eSwall 	 * don't double the number of files owned by him/her.
17595d7ed8eSwall 	 */
17695d7ed8eSwall 	for (i = 0; i < numentries ; i++) {
17795d7ed8eSwall 		ptr = namelist;
17895d7ed8eSwall 		entryfound = 0;
17995d7ed8eSwall 
18095d7ed8eSwall 		while (*ptr) {
181ac264888Swall 			if (isowner(*ptr,queue[i]->d_name))
18295d7ed8eSwall 				++entryfound;
18395d7ed8eSwall 			++ptr;
18495d7ed8eSwall 		}
18595d7ed8eSwall 		if (entryfound)
18695d7ed8eSwall 			++numfiles;
18795d7ed8eSwall 	}
18895d7ed8eSwall 	return(numfiles);
18995d7ed8eSwall }
19095d7ed8eSwall 
19195d7ed8eSwall /*
19295d7ed8eSwall  * Print the queue. If only jobs belonging to a certain person(s) are requested,
19395d7ed8eSwall  * only print jobs that belong to that person(s).
19495d7ed8eSwall  */
19595d7ed8eSwall printqueue(namelist)
19695d7ed8eSwall char **namelist;
19795d7ed8eSwall {
19895d7ed8eSwall 	int i;					/* for loop index */
19995d7ed8eSwall 	int rank = 1;				/* rank of a job */
20095d7ed8eSwall 	int entryfound;				/* found file owned by user(s)*/
20195d7ed8eSwall 	int printrank();			/* print the rank of a job */
20295d7ed8eSwall 	int plastrun();				/* print the last time the
20395d7ed8eSwall 						   spooling area was updated */
204ac264888Swall 	int powner();				/* print the name of the owner
205ac264888Swall 						   of the job */
20695d7ed8eSwall 	char **ptr;				/* scratch pointer */
20795d7ed8eSwall 	struct stat stbuf;			/* buffer for file stats */
20895d7ed8eSwall 
20995d7ed8eSwall 
21095d7ed8eSwall 	/*
21195d7ed8eSwall 	 * Print the time the spooling area was last modified and the header
21295d7ed8eSwall 	 * for the queue.
21395d7ed8eSwall 	 */
21495d7ed8eSwall 	plastrun();
21595d7ed8eSwall 	printf(" Rank	  Execution Date     Owner     Job #   Job Name\n");
21695d7ed8eSwall 
21795d7ed8eSwall 	/*
21895d7ed8eSwall 	 * Print the queue. If a certain name(s) was requested, print only jobs
21995d7ed8eSwall 	 * belonging to that person(s), otherwise print the entire queue.
22095d7ed8eSwall 	 * Once again, we have to use "entryfound" (rather than simply
22195d7ed8eSwall 	 * comparing each command line argument) so that if a person's name
22295d7ed8eSwall 	 * appears twice we don't print each file owned by him/her twice.
22395d7ed8eSwall 	 *
22495d7ed8eSwall 	 *
22595d7ed8eSwall 	 * "printrank", "printdate", and "printjobname" all take existing
22695d7ed8eSwall 	 * data and display it in a friendly manner.
22795d7ed8eSwall 	 *
22895d7ed8eSwall 	 */
22995d7ed8eSwall 	for (i = 0; i < numentries; i++) {
23095d7ed8eSwall 		if ((stat(queue[i]->d_name, &stbuf)) < 0) {
23195d7ed8eSwall 			continue;
23295d7ed8eSwall 		}
23395d7ed8eSwall 		if (namewanted) {
23495d7ed8eSwall 			ptr = namelist;
23595d7ed8eSwall 			entryfound = 0;
23695d7ed8eSwall 
23795d7ed8eSwall 			while (*ptr) {
238ac264888Swall 				if (isowner(*ptr,queue[i]->d_name))
23995d7ed8eSwall 					++entryfound;
24095d7ed8eSwall 				++ptr;
24195d7ed8eSwall 			}
24295d7ed8eSwall 			if (!entryfound)
24395d7ed8eSwall 				continue;
24495d7ed8eSwall 		}
24595d7ed8eSwall 		printrank(rank++);
24695d7ed8eSwall 		printdate(queue[i]->d_name);
247ac264888Swall 		powner(queue[i]->d_name);
24895d7ed8eSwall 		printf("%5d",stbuf.st_ino);
24995d7ed8eSwall 		printjobname(queue[i]->d_name);
25095d7ed8eSwall 	}
25195d7ed8eSwall 	++ptr;
25295d7ed8eSwall }
25395d7ed8eSwall 
25495d7ed8eSwall /*
255ac264888Swall  * See if "name" owns "job".
25695d7ed8eSwall  */
257ac264888Swall isowner(name,job)
258ac264888Swall char *name;
259ac264888Swall char *job;
26095d7ed8eSwall {
2611ed914fbSmckusick 	char buf[128];			/* buffer for 1st line of spoolfile
262ac264888Swall 					   header */
263ac264888Swall 	FILE *infile;			/* I/O stream to spoolfile */
26495d7ed8eSwall 
265ac264888Swall 	if ((infile = fopen(job,"r")) == NULL) {
266ac264888Swall 		fprintf(stderr,"Couldn't open spoolfile ");
267ac264888Swall 		perror(job);
268ac264888Swall 		return(0);
269ac264888Swall 	}
27095d7ed8eSwall 
2711ed914fbSmckusick 	if (fscanf(infile,"# owner: %127s%*[^\n]\n",buf) != 1) {
272ac264888Swall 		fclose(infile);
273ac264888Swall 		return(0);
27495d7ed8eSwall 	}
275ac264888Swall 
276ac264888Swall 	fclose(infile);
277ac264888Swall 	return((strcmp(name,buf) == 0) ? 1 : 0);
27895d7ed8eSwall }
27995d7ed8eSwall 
28095d7ed8eSwall /*
281ac264888Swall  * Print the owner of the job. This is stored on the first line of the
282ac264888Swall  * spoolfile. If we run into trouble getting the name, we'll just print "???".
283ac264888Swall  */
284ac264888Swall powner(file)
285ac264888Swall char *file;
286ac264888Swall {
2871ed914fbSmckusick 	char owner[10];				/* the owner */
288ac264888Swall 	FILE *infile;				/* I/O stream to spoolfile */
289ac264888Swall 
290ac264888Swall 	/*
291ac264888Swall 	 * Open the job file and grab the first line.
292ac264888Swall 	 */
293ac264888Swall 
294ac264888Swall 	if ((infile = fopen(file,"r")) == NULL) {
295ac264888Swall 		printf("%-10.9s","???");
2961ed914fbSmckusick 		perror(file);
297ac264888Swall 		return;
298ac264888Swall 	}
299ac264888Swall 
3001ed914fbSmckusick 	if (fscanf(infile,"# owner: %9s%*[^\n]\n",owner) != 1) {
301ac264888Swall 		printf("%-10.9s","???");
302ac264888Swall 		fclose(infile);
303ac264888Swall 		return;
304ac264888Swall 	}
305ac264888Swall 
306ac264888Swall 	fclose(infile);
307ac264888Swall 	printf("%-10.9s",owner);
308ac264888Swall 
309ac264888Swall }
310ac264888Swall 
31195d7ed8eSwall /*
31295d7ed8eSwall  * Print the time the spooling area was updated.
31395d7ed8eSwall  */
31495d7ed8eSwall plastrun()
31595d7ed8eSwall {
31695d7ed8eSwall 	struct timeval now;			/* time it is right now */
31795d7ed8eSwall 	struct timezone zone;			/* NOT USED */
31895d7ed8eSwall 	struct tm *loc;				/* detail of time it is right */
31995d7ed8eSwall 	u_long lasttime;			/* last update time in seconds
32095d7ed8eSwall 						   since 1/1/70 */
32195d7ed8eSwall 	FILE *last;				/* file where last update hour
32295d7ed8eSwall 						   is stored */
32395d7ed8eSwall 
32495d7ed8eSwall 
32595d7ed8eSwall 	/*
32695d7ed8eSwall 	 * Open the file where the last update time is stored, and grab the
32795d7ed8eSwall 	 * last update hour. The update time is measured in seconds since
32895d7ed8eSwall 	 * 1/1/70.
32995d7ed8eSwall 	 */
33095d7ed8eSwall 	if ((last = fopen(LASTFILE,"r")) == NULL) {
33195d7ed8eSwall 		perror(LASTFILE);
33295d7ed8eSwall 		exit(1);
33395d7ed8eSwall 	}
334*c7338628Sbostic 	fscanf(last,"%lu",&lasttime);
33595d7ed8eSwall 	fclose(last);
33695d7ed8eSwall 
33795d7ed8eSwall 	/*
33895d7ed8eSwall 	 * Get a broken down representation of the last update time.
33995d7ed8eSwall 	 */
34095d7ed8eSwall 	loc = localtime(&lasttime);
34195d7ed8eSwall 
34295d7ed8eSwall 	/*
34395d7ed8eSwall 	 * Print the time that the spooling area was last updated.
34495d7ed8eSwall 	 */
34595d7ed8eSwall 	printf("\n LAST EXECUTION TIME: %s ",mthnames[loc->tm_mon]);
34695d7ed8eSwall 	printf("%d, 19%d ",loc->tm_mday,loc->tm_year);
34795d7ed8eSwall 	printf("at %d:%02d\n\n",loc->tm_hour,loc->tm_min);
34895d7ed8eSwall }
34995d7ed8eSwall 
35095d7ed8eSwall /*
35195d7ed8eSwall  * Print the rank of a job. (I've got to admit it, I stole it from "lpq")
35295d7ed8eSwall  */
35395d7ed8eSwall static
35495d7ed8eSwall printrank(n)
35595d7ed8eSwall {
35695d7ed8eSwall 	static char *r[] = {
35795d7ed8eSwall 		"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
35895d7ed8eSwall 	};
35995d7ed8eSwall 
36095d7ed8eSwall 	if ((n/10) == 1)
36195d7ed8eSwall 		 printf("%3d%-5s", n,"th");
36295d7ed8eSwall 	else
36395d7ed8eSwall 		 printf("%3d%-5s", n, r[n%10]);
36495d7ed8eSwall }
36595d7ed8eSwall 
36695d7ed8eSwall /*
36795d7ed8eSwall  * Print the date that a job is to be executed. This takes some manipulation
36895d7ed8eSwall  * of the file name.
36995d7ed8eSwall  */
37095d7ed8eSwall printdate(filename)
37195d7ed8eSwall char *filename;
37295d7ed8eSwall {
37395d7ed8eSwall 	int yday  =  0;				/* day of year file will be
37495d7ed8eSwall 						   executed */
37595d7ed8eSwall 	int min	  =  0;				/* min. file will be executed */
37695d7ed8eSwall 	int hour  =  0;				/* hour file will be executed */
37795d7ed8eSwall 	int day	  =  0;				/* day file will be executed */
37895d7ed8eSwall 	int month =  0;				/* month file will be executed*/
37995d7ed8eSwall 	int year  =  0;				/* year file will be executed */
38095d7ed8eSwall 	int get_mth_day();			/* convert a day of year to a
38195d7ed8eSwall 						   month and day of month */
38295d7ed8eSwall 	char date[18];				/* reformatted execution date */
38395d7ed8eSwall 
38495d7ed8eSwall 	/*
38595d7ed8eSwall 	 * Pick off the necessary info from the file name and convert the day
38695d7ed8eSwall 	 * of year to a month and day of month.
38795d7ed8eSwall 	 */
38895d7ed8eSwall 	sscanf(filename,"%2d.%3d.%2d%2d",&year,&yday,&hour,&min);
38995d7ed8eSwall 	get_mth_day(year,yday,&month,&day);
39095d7ed8eSwall 
39195d7ed8eSwall 	/*
39295d7ed8eSwall 	 * Format the execution date of a job.
39395d7ed8eSwall 	 */
39495d7ed8eSwall 	sprintf(date,"%3s %2d, 19%2d %02d:%02d",mthnames[month],
39595d7ed8eSwall 						    day, year,hour,min);
39695d7ed8eSwall 
39795d7ed8eSwall 	/*
39895d7ed8eSwall 	 * Print the date the job will be executed.
39995d7ed8eSwall 	 */
40095d7ed8eSwall 	printf("%-21.18s",date);
40195d7ed8eSwall }
40295d7ed8eSwall 
40395d7ed8eSwall /*
40495d7ed8eSwall  * Given a day of the year, calculate the month and day of month.
40595d7ed8eSwall  */
40695d7ed8eSwall get_mth_day(year,dayofyear,month,day)
40795d7ed8eSwall int year, dayofyear, *month, *day;
40895d7ed8eSwall 
40995d7ed8eSwall {
41095d7ed8eSwall 
41195d7ed8eSwall 	int i = 1;				/* for loop index */
41295d7ed8eSwall 	int leap;				/* are we dealing with a leap
41395d7ed8eSwall 						   year? */
41495d7ed8eSwall 						/* Table of the number of days
41595d7ed8eSwall 						   in each month of the year.
41695d7ed8eSwall 
41795d7ed8eSwall 						     dofy_tab[1] -- regular year
41895d7ed8eSwall 						     dofy_tab[2] -- leap year
41995d7ed8eSwall 									      */
42095d7ed8eSwall 
42195d7ed8eSwall 	static int dofy_tab[2][13] = {
42295d7ed8eSwall 		{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
42395d7ed8eSwall 		{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
42495d7ed8eSwall 	};
42595d7ed8eSwall 
42695d7ed8eSwall 	/*
42795d7ed8eSwall 	 * Are we dealing with a leap year?
42895d7ed8eSwall 	 */
42995d7ed8eSwall 	leap = ((year%4 == 0 && year%100 != 0) || year%100 == 0);
43095d7ed8eSwall 
43195d7ed8eSwall 	/*
43295d7ed8eSwall 	 * Calculate the month of the year and day of the month.
43395d7ed8eSwall 	 */
43495d7ed8eSwall 	while (dayofyear >= dofy_tab[leap][i]) {
43595d7ed8eSwall 		dayofyear -= dofy_tab[leap][i++];
43695d7ed8eSwall 		++(*month);
43795d7ed8eSwall 	}
43895d7ed8eSwall 	*day = (dayofyear + 1);
43995d7ed8eSwall }
44095d7ed8eSwall 
44195d7ed8eSwall /*
44295d7ed8eSwall  * Print a job name. If the old "at" has been used to create the spoolfile,
44395d7ed8eSwall  * the three line header that the new version of "at" puts in the spoolfile.
44495d7ed8eSwall  * Thus, we just print "???".
44595d7ed8eSwall  */
44695d7ed8eSwall printjobname(file)
44795d7ed8eSwall char *file;
44895d7ed8eSwall {
449ac264888Swall 	char *ptr;				/* scratch pointer */
4501ed914fbSmckusick 	char jobname[28];			/* the job name */
45195d7ed8eSwall 	FILE *filename;				/* job file in spooling area */
45295d7ed8eSwall 
45395d7ed8eSwall 	/*
454ac264888Swall 	 * Open the job file and grab the second line.
45595d7ed8eSwall 	 */
45695d7ed8eSwall 	printf("   ");
45795d7ed8eSwall 
45895d7ed8eSwall 	if ((filename = fopen(file,"r")) == NULL) {
45995d7ed8eSwall 		printf("%.27s\n", "???");
4601ed914fbSmckusick 		perror(file);
46195d7ed8eSwall 		return;
46295d7ed8eSwall 	}
463ac264888Swall 	/*
4641ed914fbSmckusick 	 * Skip over the first line.
465ac264888Swall 	 */
4661ed914fbSmckusick 	fscanf(filename,"%*[^\n]\n");
467ac264888Swall 
468ac264888Swall 	/*
469ac264888Swall 	 * Now get the job name.
470ac264888Swall 	 */
4711ed914fbSmckusick 	if (fscanf(filename,"# jobname: %27s%*[^\n]\n",jobname) != 1) {
47295d7ed8eSwall 		printf("%.27s\n", "???");
47395d7ed8eSwall 		fclose(filename);
47495d7ed8eSwall 		return;
47595d7ed8eSwall 	}
47695d7ed8eSwall 	fclose(filename);
47795d7ed8eSwall 
47895d7ed8eSwall 	/*
47995d7ed8eSwall 	 * Put a pointer at the begining of the line and remove the basename
48095d7ed8eSwall 	 * from the job file.
48195d7ed8eSwall 	 */
482ac264888Swall 	ptr = jobname;
483ac264888Swall 	if ((ptr = (char *)rindex(jobname,'/')) != 0)
484ac264888Swall 		++ptr;
48595d7ed8eSwall 	else
486ac264888Swall 		ptr = jobname;
48795d7ed8eSwall 
488ac264888Swall 	if (strlen(ptr) > 23)
489ac264888Swall 		printf("%.23s ...\n",ptr);
490ac264888Swall 	else
491ac264888Swall 		printf("%.27s\n",ptr);
49295d7ed8eSwall }
49395d7ed8eSwall 
49495d7ed8eSwall /*
49595d7ed8eSwall  * Do we want to include a file in the queue? (used by "scandir") We are looking
49695d7ed8eSwall  * for files with following syntax: yy.ddd.hhhh. so the test is made to see if
49795d7ed8eSwall  * the file name has three dots in it. This test will suffice since the only
49895d7ed8eSwall  * other files in /usr/spool/at don't have any dots in their name.
49995d7ed8eSwall  */
50095d7ed8eSwall filewanted(direntry)
50195d7ed8eSwall struct direct *direntry;
50295d7ed8eSwall {
50395d7ed8eSwall 	int numdot = 0;
50495d7ed8eSwall 	char *filename;
50595d7ed8eSwall 
50695d7ed8eSwall 	filename = direntry->d_name;
50795d7ed8eSwall 	while (*filename)
50895d7ed8eSwall 		numdot += (*(filename++) == '.');
50995d7ed8eSwall 	return(numdot == 3);
51095d7ed8eSwall }
51195d7ed8eSwall 
51295d7ed8eSwall /*
51395d7ed8eSwall  * Sort files by time of creation. (used by "scandir")
51495d7ed8eSwall  */
51595d7ed8eSwall creation(d1, d2)
51695d7ed8eSwall struct direct **d1, **d2;
51795d7ed8eSwall {
51895d7ed8eSwall 	struct stat stbuf1, stbuf2;
51995d7ed8eSwall 
52095d7ed8eSwall 	if (stat((*d1)->d_name,&stbuf1) < 0)
52195d7ed8eSwall 		return(1);
52295d7ed8eSwall 
52395d7ed8eSwall 	if (stat((*d2)->d_name,&stbuf2) < 0)
52495d7ed8eSwall 		return(1);
52595d7ed8eSwall 
52695d7ed8eSwall 	return(stbuf1.st_ctime < stbuf2.st_ctime);
52795d7ed8eSwall }
52895d7ed8eSwall 
52995d7ed8eSwall /*
53095d7ed8eSwall  * Print usage info and exit.
53195d7ed8eSwall  */
53295d7ed8eSwall usage()
53395d7ed8eSwall {
53495d7ed8eSwall 	fprintf(stderr,"usage:	atq [-c] [-n] [name ...]\n");
53595d7ed8eSwall 	exit(1);
53695d7ed8eSwall }
537