static char sccsid
[] = "@(#)atq.c 1.2 (Berkeley) %G%";
* Synopsis: atq [ -c ] [ -n ] [ name ... ]
* Print the queue of files waiting to be executed. These files
* were created by using the "at" command and are located in the
* directory "/usr/spool/at".
* Computer Systems Research Group
* University of California @ Berkeley
# define ATDIR "/usr/spool/at" /* spooling area */
# define LASTFILE "/usr/spool/at/lasttimedone" /* update time record
static char *mthnames
[12] = {
"Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec",
int numentries
; /* number of entries in spooling area */
int namewanted
= 0; /* only print jobs belonging to a
struct direct
**queue
; /* the queue itself */
int cflag
= 0; /* print in order of creation time */
int nflag
= 0; /* just print the number of jobs in
int usage(); /* print usage info and exit */
int creation(); /* sort jobs by date of creation */
int alphasort(); /* sort jobs by date of execution */
int filewanted(); /* should a file be included in queue?*/
int printqueue(); /* print the queue */
int countfiles(); /* count the number of files in queue
char **namelist
; /* array of specific name(s) requested*/
* Interpret command line flags if they exist.
while (argc
> 0 && **argv
== '-') {
while (**argv
) switch (*(*argv
)++) {
* If a certain name (or names) is requested, set a pointer to the
* Move to the spooling area and scan the directory, placing the
* files in the queue structure. The queue comes back sorted by
* execution time or creation time.
if (chdir(ATDIR
) == -1) {
if ((numentries
= scandir(".",&queue
,filewanted
, (cflag
) ? creation
:
* Either print a message stating:
* 1) that the spooling area is empty.
* 2) the number of jobs in the spooling area.
* 3) the number of jobs in the spooling area belonging to
* 4) that the person requested doesn't have any files in the
* or send the queue off to "printqueue" for printing.
* This whole process might seem a bit elaborate, but it's worthwhile
* to print some informative messages for the user.
if ((numentries
== 0) && (!nflag
)) {
printf("no files in queue.\n");
printf("%d\n",(namewanted
) ? countfiles(namelist
) : numentries
);
if ((namewanted
) && (countfiles(namelist
) == 0)) {
printf("no files for %s.\n", (argc
== 1) ?
*argv
: "specified users");
* Count the number of jobs in the spooling area owned by a certain person(s).
int i
; /* for loop index */
int entryfound
; /* found file owned by user(s)*/
int numfiles
= 0; /* number of files owned by a
char **ptr
; /* scratch pointer */
struct stat stbuf
; /* buffer for file stats */
* For each file in the queue, see if the user(s) own the file. We
* have to use "entryfound" (rather than simply incrementing "numfiles")
* so that if a person's name appears twice on the command line we
* don't double the number of files owned by him/her.
for (i
= 0; i
< numentries
; i
++) {
if ((stat(queue
[i
]->d_name
, &stbuf
)) < 0) {
if (getid(*ptr
) == stbuf
.st_uid
)
* Print the queue. If only jobs belonging to a certain person(s) are requested,
* only print jobs that belong to that person(s).
int i
; /* for loop index */
int rank
= 1; /* rank of a job */
int entryfound
; /* found file owned by user(s)*/
int printrank(); /* print the rank of a job */
int plastrun(); /* print the last time the
spooling area was updated */
int getid(); /* get uid of a person */
char **ptr
; /* scratch pointer */
char *getname(); /* get the login name of a
person using their uid */
struct stat stbuf
; /* buffer for file stats */
* Print the time the spooling area was last modified and the header
printf(" Rank Execution Date Owner Job # Job Name\n");
* Print the queue. If a certain name(s) was requested, print only jobs
* belonging to that person(s), otherwise print the entire queue.
* Once again, we have to use "entryfound" (rather than simply
* comparing each command line argument) so that if a person's name
* appears twice we don't print each file owned by him/her twice.
* "printrank", "printdate", and "printjobname" all take existing
* data and display it in a friendly manner.
for (i
= 0; i
< numentries
; i
++) {
if ((stat(queue
[i
]->d_name
, &stbuf
)) < 0) {
if (getid(*ptr
) == stbuf
.st_uid
)
printdate(queue
[i
]->d_name
);
printf("%-10.9s",getname(stbuf
.st_uid
));
printf("%5d",stbuf
.st_ino
);
printjobname(queue
[i
]->d_name
);
* Get the full login name of a person using his/her user id.
struct passwd
*pwdinfo
; /* password info structure */
if ((pwdinfo
= getpwuid(uid
)) == 0) {
return(pwdinfo
->pw_name
);
* Get the uid of a person using his/her login name. Return -1 if no
* such account name exists.
struct passwd
*pwdinfo
; /* password info structure */
if ((pwdinfo
= getpwnam(name
)) == 0)
* Print the time the spooling area was updated.
struct timeval now
; /* time it is right now */
struct timezone zone
; /* NOT USED */
struct tm
*loc
; /* detail of time it is right */
u_long lasttime
; /* last update time in seconds
FILE *last
; /* file where last update hour
* Open the file where the last update time is stored, and grab the
* last update hour. The update time is measured in seconds since
if ((last
= fopen(LASTFILE
,"r")) == NULL
) {
fscanf(last
,"%d",(u_long
) &lasttime
);
* Get a broken down representation of the last update time.
loc
= localtime(&lasttime
);
* Print the time that the spooling area was last updated.
printf("\n LAST EXECUTION TIME: %s ",mthnames
[loc
->tm_mon
]);
printf("%d, 19%d ",loc
->tm_mday
,loc
->tm_year
);
printf("at %d:%02d\n\n",loc
->tm_hour
,loc
->tm_min
);
* Print the rank of a job. (I've got to admit it, I stole it from "lpq")
"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
printf("%3d%-5s", n
,"th");
printf("%3d%-5s", n
, r
[n
%10]);
* Print the date that a job is to be executed. This takes some manipulation
int yday
= 0; /* day of year file will be
int min
= 0; /* min. file will be executed */
int hour
= 0; /* hour file will be executed */
int day
= 0; /* day file will be executed */
int month
= 0; /* month file will be executed*/
int year
= 0; /* year file will be executed */
int get_mth_day(); /* convert a day of year to a
month and day of month */
char date
[18]; /* reformatted execution date */
* Pick off the necessary info from the file name and convert the day
* of year to a month and day of month.
sscanf(filename
,"%2d.%3d.%2d%2d",&year
,&yday
,&hour
,&min
);
get_mth_day(year
,yday
,&month
,&day
);
* Format the execution date of a job.
sprintf(date
,"%3s %2d, 19%2d %02d:%02d",mthnames
[month
],
* Print the date the job will be executed.
* Given a day of the year, calculate the month and day of month.
get_mth_day(year
,dayofyear
,month
,day
)
int year
, dayofyear
, *month
, *day
;
int i
= 1; /* for loop index */
int leap
; /* are we dealing with a leap
/* Table of the number of days
in each month of the year.
dofy_tab[1] -- regular year
static int dofy_tab
[2][13] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
* Are we dealing with a leap year?
leap
= ((year
%4 == 0 && year
%100 != 0) || year
%100 == 0);
* Calculate the month of the year and day of the month.
while (dayofyear
>= dofy_tab
[leap
][i
]) {
dayofyear
-= dofy_tab
[leap
][i
++];
* Print a job name. If the old "at" has been used to create the spoolfile,
* the three line header that the new version of "at" puts in the spoolfile.
* Thus, we just print "???".
char jobname
[80]; /* the job name */
FILE *filename
; /* job file in spooling area */
* Open the job file and grab the first line.
if ((filename
= fopen(file
,"r")) == NULL
) {
printf("%.27s\n", "???");
if (fscanf(filename
,"# jobname: %s",jobname
) != 1) {
printf("%.27s\n", "???");
* Put a pointer at the begining of the line and remove the basename
if ((ch
= (char *)rindex(jobname
,'/')) != 0)
* Do we want to include a file in the queue? (used by "scandir") We are looking
* for files with following syntax: yy.ddd.hhhh. so the test is made to see if
* the file name has three dots in it. This test will suffice since the only
* other files in /usr/spool/at don't have any dots in their name.
filename
= direntry
->d_name
;
numdot
+= (*(filename
++) == '.');
* Sort files by time of creation. (used by "scandir")
struct direct
**d1
, **d2
;
struct stat stbuf1
, stbuf2
;
if (stat((*d1
)->d_name
,&stbuf1
) < 0)
if (stat((*d2
)->d_name
,&stbuf2
) < 0)
return(stbuf1
.st_ctime
< stbuf2
.st_ctime
);
* Print usage info and exit.
fprintf(stderr
,"usage: atq [-c] [-n] [name ...]\n");