1032624d5Sbasabi /*
2*d1419d5aSNobutomo Nakano * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3032624d5Sbasabi * Use is subject to license terms.
4032624d5Sbasabi */
5032624d5Sbasabi
67c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
77c478bd9Sstevel@tonic-gate /* All Rights Reserved */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate
107c478bd9Sstevel@tonic-gate /*
117c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California.
127c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
137c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
147c478bd9Sstevel@tonic-gate */
157c478bd9Sstevel@tonic-gate
167c478bd9Sstevel@tonic-gate /*
177c478bd9Sstevel@tonic-gate *
187c478bd9Sstevel@tonic-gate * Synopsis: atq [ -c ] [ -n ] [ name ... ]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate *
217c478bd9Sstevel@tonic-gate * Print the queue of files waiting to be executed. These files
227c478bd9Sstevel@tonic-gate * were created by using the "at" command and are located in the
237c478bd9Sstevel@tonic-gate * directory defined by ATDIR.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/file.h>
297c478bd9Sstevel@tonic-gate #include <dirent.h>
307c478bd9Sstevel@tonic-gate #include <sys/stat.h>
317c478bd9Sstevel@tonic-gate #include <time.h>
327c478bd9Sstevel@tonic-gate #include <pwd.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <locale.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
373d63ea05Sas145665 #include <stdlib.h>
383d63ea05Sas145665 #include <string.h>
397c478bd9Sstevel@tonic-gate #include "cron.h"
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate extern char *errmsg();
427c478bd9Sstevel@tonic-gate extern char *strchr();
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate * Months of the year
467c478bd9Sstevel@tonic-gate */
477c478bd9Sstevel@tonic-gate static char *mthnames[12] = {
487c478bd9Sstevel@tonic-gate "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
497c478bd9Sstevel@tonic-gate "Aug", "Sep", "Oct", "Nov", "Dec",
507c478bd9Sstevel@tonic-gate };
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate int numentries; /* number of entries in spooling area */
537c478bd9Sstevel@tonic-gate int namewanted = 0; /* print jobs for a certain person */
547c478bd9Sstevel@tonic-gate struct dirent **queue; /* the queue itself */
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate #define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)"
577c478bd9Sstevel@tonic-gate #define NOTALLOWED "you are not authorized to use at. Sorry."
587c478bd9Sstevel@tonic-gate
59032624d5Sbasabi static void atabortperror(char *msg);
60032624d5Sbasabi static void atabort(char *msg);
61032624d5Sbasabi static void aterror(char *msg);
62032624d5Sbasabi static void atperror(char *msg);
63032624d5Sbasabi static void usage(void);
64032624d5Sbasabi static void printjobname(char *file);
65032624d5Sbasabi static void printdate(char *filename);
66032624d5Sbasabi static void printrank(int n);
67032624d5Sbasabi static void printqueue(uid_t *uidlist, int nuids);
687c478bd9Sstevel@tonic-gate
69032624d5Sbasabi int
main(int argc,char ** argv)70032624d5Sbasabi main(int argc, char **argv)
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate
73032624d5Sbasabi struct passwd *pp; /* password file entry pointer */
747c478bd9Sstevel@tonic-gate struct passwd pr;
75032624d5Sbasabi int i;
767c478bd9Sstevel@tonic-gate int cflag = 0; /* print in order of creation time */
777c478bd9Sstevel@tonic-gate int nflag = 0; /* just print the number of jobs in */
787c478bd9Sstevel@tonic-gate /* queue */
797c478bd9Sstevel@tonic-gate extern int creation(); /* sort jobs by date of creation */
807c478bd9Sstevel@tonic-gate extern int execution(); /* sort jobs by date of execution */
817c478bd9Sstevel@tonic-gate int filewanted(); /* should file be included in queue? */
827c478bd9Sstevel@tonic-gate int countfiles(); /* count the number of files in queue */
837c478bd9Sstevel@tonic-gate /* for a given person */
847c478bd9Sstevel@tonic-gate uid_t *uidlist = NULL; /* array of spec. owner ID(s) requ. */
857c478bd9Sstevel@tonic-gate int argnum = 0; /* number of names passed as arg't */
867c478bd9Sstevel@tonic-gate int badarg = 0;
877c478bd9Sstevel@tonic-gate char *c;
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate --argc, ++argv;
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
937c478bd9Sstevel@tonic-gate pp = getpwuid(getuid());
947c478bd9Sstevel@tonic-gate pr.pw_uid = pp->pw_uid;
957c478bd9Sstevel@tonic-gate pr.pw_name = pp->pw_name;
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate if (pp == NULL)
987c478bd9Sstevel@tonic-gate atabort(INVALIDUSER);
997c478bd9Sstevel@tonic-gate if (!allowed(pp->pw_name, ATALLOW, ATDENY))
1007c478bd9Sstevel@tonic-gate atabort(NOTALLOWED);
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate * Interpret command line flags if they exist.
1047c478bd9Sstevel@tonic-gate */
1057c478bd9Sstevel@tonic-gate while (argc > 0 && **argv == '-') {
1067c478bd9Sstevel@tonic-gate (*argv)++;
1077c478bd9Sstevel@tonic-gate while (**argv) {
1087c478bd9Sstevel@tonic-gate switch (*(*argv)++) {
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate case 'c' : cflag++;
1117c478bd9Sstevel@tonic-gate break;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate case 'n' : nflag++;
1147c478bd9Sstevel@tonic-gate break;
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate default : usage();
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate --argc, ++argv;
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate * If a certain name (or names) is requested, set a pointer to the
1257c478bd9Sstevel@tonic-gate * beginning of the list.
1267c478bd9Sstevel@tonic-gate */
1277c478bd9Sstevel@tonic-gate if (argc > 0) {
1287c478bd9Sstevel@tonic-gate ++namewanted;
1297c478bd9Sstevel@tonic-gate uidlist = (uid_t *)malloc(argc * sizeof (uid_t));
1307c478bd9Sstevel@tonic-gate if (uidlist == NULL)
1317c478bd9Sstevel@tonic-gate atabortperror("can't allocate list of users");
1327c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) {
133*d1419d5aSNobutomo Nakano if (cron_admin(pr.pw_name) ||
1347c478bd9Sstevel@tonic-gate strcmp(pr.pw_name, argv[i]) == 0) {
1357c478bd9Sstevel@tonic-gate if ((pp = getpwnam(argv[i])) == NULL) {
1367c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
1377c478bd9Sstevel@tonic-gate "atq: No such user %s\n", argv[i]);
1387c478bd9Sstevel@tonic-gate exit(1);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate uidlist[argnum] = pp->pw_uid;
1417c478bd9Sstevel@tonic-gate argnum++;
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate else
1447c478bd9Sstevel@tonic-gate badarg++;
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate if (badarg)
1477c478bd9Sstevel@tonic-gate if (argnum)
1487c478bd9Sstevel@tonic-gate printf("Printing queue information only "
1497c478bd9Sstevel@tonic-gate "for %s:\n", pr.pw_name);
1507c478bd9Sstevel@tonic-gate else {
1517c478bd9Sstevel@tonic-gate printf("atq: Non-priviledged user cannot "
1527c478bd9Sstevel@tonic-gate "request information regarding other "
1537c478bd9Sstevel@tonic-gate "users\n");
1547c478bd9Sstevel@tonic-gate exit(1);
1557c478bd9Sstevel@tonic-gate }
156*d1419d5aSNobutomo Nakano } else if (!cron_admin(pr.pw_name)) {
1577c478bd9Sstevel@tonic-gate /* no argument specified and the invoker is not root */
1587c478bd9Sstevel@tonic-gate ++namewanted;
1597c478bd9Sstevel@tonic-gate argnum = 1;
1607c478bd9Sstevel@tonic-gate if ((uidlist = (uid_t *)malloc(sizeof (uid_t))) == NULL)
1617c478bd9Sstevel@tonic-gate atabortperror("can't allocate list of users");
1627c478bd9Sstevel@tonic-gate *uidlist = pr.pw_uid;
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate /*
1667c478bd9Sstevel@tonic-gate * Move to the spooling area and scan the directory, placing the
1677c478bd9Sstevel@tonic-gate * files in the queue structure. The queue comes back sorted by
1687c478bd9Sstevel@tonic-gate * execution time or creation time.
1697c478bd9Sstevel@tonic-gate */
1707c478bd9Sstevel@tonic-gate if (chdir(ATDIR) == -1)
1717c478bd9Sstevel@tonic-gate atabortperror(ATDIR);
1722b52f2afSjk217608 if ((numentries = scandir(".", &queue, filewanted,
1737c478bd9Sstevel@tonic-gate (cflag) ? creation : execution)) < 0)
1747c478bd9Sstevel@tonic-gate atabortperror(ATDIR);
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate * Either print a message stating:
1797c478bd9Sstevel@tonic-gate *
1807c478bd9Sstevel@tonic-gate * 1) that the spooling area is empty.
1817c478bd9Sstevel@tonic-gate * 2) the number of jobs in the spooling area.
1827c478bd9Sstevel@tonic-gate * 3) the number of jobs in the spooling area belonging to
1837c478bd9Sstevel@tonic-gate * a certain person.
1847c478bd9Sstevel@tonic-gate * 4) that the person requested doesn't have any files in the
1857c478bd9Sstevel@tonic-gate * spooling area.
1867c478bd9Sstevel@tonic-gate *
1877c478bd9Sstevel@tonic-gate * or send the queue off to "printqueue" for printing.
1887c478bd9Sstevel@tonic-gate *
1897c478bd9Sstevel@tonic-gate * This whole process might seem a bit elaborate, but it's worthwhile
1907c478bd9Sstevel@tonic-gate * to print some informative messages for the user.
1917c478bd9Sstevel@tonic-gate *
1927c478bd9Sstevel@tonic-gate */
1937c478bd9Sstevel@tonic-gate if ((numentries == 0) && (!nflag)) {
1947c478bd9Sstevel@tonic-gate printf("no files in queue.\n");
1957c478bd9Sstevel@tonic-gate exit(0);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate if (nflag) {
1987c478bd9Sstevel@tonic-gate printf("%d\n", (namewanted) ?
1997c478bd9Sstevel@tonic-gate countfiles(uidlist, argnum) : numentries);
2007c478bd9Sstevel@tonic-gate exit(0);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate if ((namewanted) && (countfiles(uidlist, argnum) == 0)) {
2037c478bd9Sstevel@tonic-gate if (argnum == 1)
2047c478bd9Sstevel@tonic-gate if (argnum != argc) c = pr.pw_name;
2057c478bd9Sstevel@tonic-gate else c = *argv;
2067c478bd9Sstevel@tonic-gate printf("no files for %s.\n", (argnum == 1) ?
2077c478bd9Sstevel@tonic-gate c : "specified users");
2087c478bd9Sstevel@tonic-gate exit(0);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate printqueue(uidlist, argnum);
211032624d5Sbasabi return (0);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * Count the number of jobs in the spooling area owned by a certain person(s).
2167c478bd9Sstevel@tonic-gate */
217032624d5Sbasabi int
countfiles(uid_t * uidlist,int nuids)218032624d5Sbasabi countfiles(uid_t *uidlist, int nuids)
2197c478bd9Sstevel@tonic-gate {
220032624d5Sbasabi int i, j; /* for loop indices */
2217c478bd9Sstevel@tonic-gate int entryfound; /* found file owned by users */
2227c478bd9Sstevel@tonic-gate int numfiles = 0; /* number of files owned by a */
2237c478bd9Sstevel@tonic-gate /* certain person(s) */
224032624d5Sbasabi uid_t *ptr; /* scratch pointer */
2257c478bd9Sstevel@tonic-gate struct stat stbuf; /* buffer for file stats */
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate /*
2297c478bd9Sstevel@tonic-gate * For each file in the queue, see if the user(s) own the file. We
2307c478bd9Sstevel@tonic-gate * have to use "entryfound" (rather than simply incrementing "numfiles")
2317c478bd9Sstevel@tonic-gate * so that if a person's name appears twice on the command line we
2327c478bd9Sstevel@tonic-gate * don't double the number of files owned by him/her.
2337c478bd9Sstevel@tonic-gate */
2347c478bd9Sstevel@tonic-gate for (i = 0; i < numentries; i++) {
2357c478bd9Sstevel@tonic-gate if ((stat(queue[i]->d_name, &stbuf)) < 0) {
2367c478bd9Sstevel@tonic-gate continue;
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate ptr = uidlist;
2397c478bd9Sstevel@tonic-gate entryfound = 0;
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate for (j = 0; j < nuids; j++) {
2427c478bd9Sstevel@tonic-gate if (*ptr == stbuf.st_uid)
2437c478bd9Sstevel@tonic-gate ++entryfound;
2447c478bd9Sstevel@tonic-gate ++ptr;
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate if (entryfound)
2477c478bd9Sstevel@tonic-gate ++numfiles;
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate return (numfiles);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /*
2537c478bd9Sstevel@tonic-gate * Print the queue. If only jobs belonging to a certain person(s) are requested,
2547c478bd9Sstevel@tonic-gate * only print jobs that belong to that person(s).
2557c478bd9Sstevel@tonic-gate */
256032624d5Sbasabi static void
printqueue(uid_t * uidlist,int nuids)257032624d5Sbasabi printqueue(uid_t *uidlist, int nuids)
2587c478bd9Sstevel@tonic-gate {
259032624d5Sbasabi int i, j; /* for loop indices */
2607c478bd9Sstevel@tonic-gate int rank; /* rank of a job */
2617c478bd9Sstevel@tonic-gate int entryfound; /* found file owned by users */
2627c478bd9Sstevel@tonic-gate char *getname();
263032624d5Sbasabi uid_t *ptr; /* scratch pointer */
2647c478bd9Sstevel@tonic-gate struct stat stbuf; /* buffer for file stats */
2657c478bd9Sstevel@tonic-gate char curqueue; /* queue of current job */
2667c478bd9Sstevel@tonic-gate char lastqueue; /* queue of previous job */
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate /*
2697c478bd9Sstevel@tonic-gate * Print the header for the queue.
2707c478bd9Sstevel@tonic-gate */
2717c478bd9Sstevel@tonic-gate printf(" Rank Execution Date Owner Job "
2727c478bd9Sstevel@tonic-gate "Queue Job Name\n");
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate * Print the queue. If a certain name(s) was requested, print only jobs
2767c478bd9Sstevel@tonic-gate * belonging to that person(s), otherwise print the entire queue.
2777c478bd9Sstevel@tonic-gate * Once again, we have to use "entryfound" (rather than simply
2787c478bd9Sstevel@tonic-gate * comparing each command line argument) so that if a person's name
2797c478bd9Sstevel@tonic-gate * appears twice we don't print each file owned by him/her twice.
2807c478bd9Sstevel@tonic-gate *
2817c478bd9Sstevel@tonic-gate *
2827c478bd9Sstevel@tonic-gate * "printrank", "printdate", and "printjobname" all take existing
2837c478bd9Sstevel@tonic-gate * data and display it in a friendly manner.
2847c478bd9Sstevel@tonic-gate *
2857c478bd9Sstevel@tonic-gate */
2867c478bd9Sstevel@tonic-gate lastqueue = '\0';
2877c478bd9Sstevel@tonic-gate for (i = 0; i < numentries; i++) {
2887c478bd9Sstevel@tonic-gate if ((stat(queue[i]->d_name, &stbuf)) < 0) {
2897c478bd9Sstevel@tonic-gate continue;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate curqueue = *(strchr(queue[i]->d_name, '.') + 1);
2927c478bd9Sstevel@tonic-gate if (curqueue != lastqueue) {
2937c478bd9Sstevel@tonic-gate rank = 1;
2947c478bd9Sstevel@tonic-gate lastqueue = curqueue;
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate if (namewanted) {
2977c478bd9Sstevel@tonic-gate ptr = uidlist;
2987c478bd9Sstevel@tonic-gate entryfound = 0;
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate for (j = 0; j < nuids; j++) {
3017c478bd9Sstevel@tonic-gate if (*ptr == stbuf.st_uid)
3027c478bd9Sstevel@tonic-gate ++entryfound;
3037c478bd9Sstevel@tonic-gate ++ptr;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate if (!entryfound)
3067c478bd9Sstevel@tonic-gate continue;
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate printrank(rank++);
3097c478bd9Sstevel@tonic-gate printdate(queue[i]->d_name);
3107c478bd9Sstevel@tonic-gate printf("%-10s ", getname(stbuf.st_uid));
3117c478bd9Sstevel@tonic-gate printf("%-14s ", queue[i]->d_name);
3127c478bd9Sstevel@tonic-gate printf(" %c", curqueue);
3137c478bd9Sstevel@tonic-gate printjobname(queue[i]->d_name);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate ++ptr;
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate /*
3197c478bd9Sstevel@tonic-gate * Get the uid of a person using his/her login name. Return -1 if no
3207c478bd9Sstevel@tonic-gate * such account name exists.
3217c478bd9Sstevel@tonic-gate */
3227c478bd9Sstevel@tonic-gate uid_t
getid(char * name)323032624d5Sbasabi getid(char *name)
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate struct passwd *pwdinfo; /* password info structure */
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate if ((pwdinfo = getpwnam(name)) == 0)
3307c478bd9Sstevel@tonic-gate return ((uid_t)-1);
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate return (pwdinfo->pw_uid);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate * Get the full login name of a person using his/her user id.
3377c478bd9Sstevel@tonic-gate */
3387c478bd9Sstevel@tonic-gate char *
getname(uid_t uid)339032624d5Sbasabi getname(uid_t uid)
3407c478bd9Sstevel@tonic-gate {
341032624d5Sbasabi struct passwd *pwdinfo; /* password info structure */
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate if ((pwdinfo = getpwuid(uid)) == 0)
3457c478bd9Sstevel@tonic-gate return ("???");
3467c478bd9Sstevel@tonic-gate return (pwdinfo->pw_name);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /*
3507c478bd9Sstevel@tonic-gate * Print the rank of a job. (I've got to admit it, I stole it from "lpq")
3517c478bd9Sstevel@tonic-gate */
352032624d5Sbasabi static void
printrank(int n)353032624d5Sbasabi printrank(int n)
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate static char *r[] = {
3567c478bd9Sstevel@tonic-gate "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
3577c478bd9Sstevel@tonic-gate };
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate if ((n/10) == 1)
3607c478bd9Sstevel@tonic-gate printf("%3d%-5s", n, "th");
3617c478bd9Sstevel@tonic-gate else
3627c478bd9Sstevel@tonic-gate printf("%3d%-5s", n, r[n%10]);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate /*
3667c478bd9Sstevel@tonic-gate * Print the date that a job is to be executed. This takes some manipulation
3677c478bd9Sstevel@tonic-gate * of the file name.
3687c478bd9Sstevel@tonic-gate */
369032624d5Sbasabi static void
printdate(char * filename)370032624d5Sbasabi printdate(char *filename)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate time_t jobdate;
373032624d5Sbasabi struct tm *unpackeddate;
3747c478bd9Sstevel@tonic-gate char date[18]; /* reformatted execution date */
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate /*
3777c478bd9Sstevel@tonic-gate * Convert the file name to a date.
3787c478bd9Sstevel@tonic-gate */
3797c478bd9Sstevel@tonic-gate jobdate = num(&filename);
3807c478bd9Sstevel@tonic-gate unpackeddate = localtime(&jobdate);
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate /* years since 1900 + base century 1900 */
3837c478bd9Sstevel@tonic-gate unpackeddate->tm_year += 1900;
3847c478bd9Sstevel@tonic-gate /*
3857c478bd9Sstevel@tonic-gate * Format the execution date of a job.
3867c478bd9Sstevel@tonic-gate */
3877c478bd9Sstevel@tonic-gate sprintf(date, "%3s %2d, %4d %02d:%02d", mthnames[unpackeddate->tm_mon],
3887c478bd9Sstevel@tonic-gate unpackeddate->tm_mday, unpackeddate->tm_year,
3897c478bd9Sstevel@tonic-gate unpackeddate->tm_hour, unpackeddate->tm_min);
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate /*
3927c478bd9Sstevel@tonic-gate * Print the date the job will be executed.
3937c478bd9Sstevel@tonic-gate */
3947c478bd9Sstevel@tonic-gate printf("%-21.18s", date);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate * Print a job name. If the old "at" has been used to create the spoolfile,
3997c478bd9Sstevel@tonic-gate * the three line header that the new version of "at" puts in the spoolfile.
4007c478bd9Sstevel@tonic-gate * Thus, we just print "???".
4017c478bd9Sstevel@tonic-gate */
402032624d5Sbasabi static void
printjobname(char * file)403032624d5Sbasabi printjobname(char *file)
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate char *ptr; /* scratch pointer */
4067c478bd9Sstevel@tonic-gate char jobname[28]; /* the job name */
4077c478bd9Sstevel@tonic-gate FILE *filename; /* job file in spooling area */
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * Open the job file and grab the third line.
4117c478bd9Sstevel@tonic-gate */
4127c478bd9Sstevel@tonic-gate printf(" ");
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate if ((filename = fopen(file, "r")) == NULL) {
4157c478bd9Sstevel@tonic-gate printf("%.27s\n", "???");
4167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "atq: Can't open job file %s: %s\n",
4177c478bd9Sstevel@tonic-gate file, errmsg(errno));
4187c478bd9Sstevel@tonic-gate return;
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate /*
4217c478bd9Sstevel@tonic-gate * Skip over the first and second lines.
4227c478bd9Sstevel@tonic-gate */
4237c478bd9Sstevel@tonic-gate fscanf(filename, "%*[^\n]\n");
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate * Now get the job name.
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate if (fscanf(filename, ": jobname: %27s%*[^\n]\n", jobname) != 1) {
4297c478bd9Sstevel@tonic-gate printf("%.27s\n", "???");
4307c478bd9Sstevel@tonic-gate fclose(filename);
4317c478bd9Sstevel@tonic-gate return;
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate fclose(filename);
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate * Put a pointer at the begining of the line and remove the basename
4377c478bd9Sstevel@tonic-gate * from the job file.
4387c478bd9Sstevel@tonic-gate */
4397c478bd9Sstevel@tonic-gate ptr = jobname;
4407c478bd9Sstevel@tonic-gate if ((ptr = (char *)strrchr(jobname, '/')) != 0)
4417c478bd9Sstevel@tonic-gate ++ptr;
4427c478bd9Sstevel@tonic-gate else
4437c478bd9Sstevel@tonic-gate ptr = jobname;
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate if (strlen(ptr) > 23)
4467c478bd9Sstevel@tonic-gate printf("%.23s ...\n", ptr);
4477c478bd9Sstevel@tonic-gate else
4487c478bd9Sstevel@tonic-gate printf("%.27s\n", ptr);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate /*
4542b52f2afSjk217608 * Sort files by queue, time of creation, and sequence. (used by "scandir")
4557c478bd9Sstevel@tonic-gate */
456032624d5Sbasabi int
creation(struct dirent ** d1,struct dirent ** d2)457032624d5Sbasabi creation(struct dirent **d1, struct dirent **d2)
4587c478bd9Sstevel@tonic-gate {
459032624d5Sbasabi char *p1, *p2;
460032624d5Sbasabi int i;
4617c478bd9Sstevel@tonic-gate struct stat stbuf1, stbuf2;
462032624d5Sbasabi int seq1, seq2;
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate if ((p1 = strchr((*d1)->d_name, '.')) == NULL)
4657c478bd9Sstevel@tonic-gate return (0);
4667c478bd9Sstevel@tonic-gate if ((p2 = strchr((*d2)->d_name, '.')) == NULL)
4677c478bd9Sstevel@tonic-gate return (0);
4687c478bd9Sstevel@tonic-gate p1++;
4697c478bd9Sstevel@tonic-gate p2++;
4707c478bd9Sstevel@tonic-gate if ((i = *p1++ - *p2++) != 0)
4717c478bd9Sstevel@tonic-gate return (i);
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate if (stat((*d1)->d_name, &stbuf1) < 0)
4747c478bd9Sstevel@tonic-gate return (0);
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate if (stat((*d2)->d_name, &stbuf2) < 0)
4777c478bd9Sstevel@tonic-gate return (0);
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate if (stbuf1.st_ctime < stbuf2.st_ctime)
4807c478bd9Sstevel@tonic-gate return (-1);
4817c478bd9Sstevel@tonic-gate else if (stbuf1.st_ctime > stbuf2.st_ctime)
4827c478bd9Sstevel@tonic-gate return (1);
4837c478bd9Sstevel@tonic-gate p1++;
4847c478bd9Sstevel@tonic-gate p2++;
4857c478bd9Sstevel@tonic-gate seq1 = atoi(p1);
4867c478bd9Sstevel@tonic-gate seq2 = atoi(p2);
4877c478bd9Sstevel@tonic-gate return (seq1 - seq2);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate /*
4912b52f2afSjk217608 * Sort files by queue, time of execution, and sequence. (used by "scandir")
4927c478bd9Sstevel@tonic-gate */
493032624d5Sbasabi int
execution(struct dirent ** d1,struct dirent ** d2)494032624d5Sbasabi execution(struct dirent **d1, struct dirent **d2)
4957c478bd9Sstevel@tonic-gate {
496032624d5Sbasabi char *p1, *p2;
497032624d5Sbasabi int i;
4987c478bd9Sstevel@tonic-gate char *name1, *name2;
499032624d5Sbasabi time_t time1, time2;
500032624d5Sbasabi int seq1, seq2;
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate name1 = (*d1)->d_name;
5037c478bd9Sstevel@tonic-gate name2 = (*d2)->d_name;
5047c478bd9Sstevel@tonic-gate if ((p1 = strchr(name1, '.')) == NULL)
5057c478bd9Sstevel@tonic-gate return (1);
5067c478bd9Sstevel@tonic-gate if ((p2 = strchr(name2, '.')) == NULL)
5077c478bd9Sstevel@tonic-gate return (1);
5087c478bd9Sstevel@tonic-gate p1++;
5097c478bd9Sstevel@tonic-gate p2++;
5107c478bd9Sstevel@tonic-gate if ((i = *p1++ - *p2++) != 0)
5117c478bd9Sstevel@tonic-gate return (i);
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate time1 = num(&name1);
5147c478bd9Sstevel@tonic-gate time2 = num(&name2);
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate if (time1 < time2)
5177c478bd9Sstevel@tonic-gate return (-1);
5187c478bd9Sstevel@tonic-gate else if (time1 > time2)
5197c478bd9Sstevel@tonic-gate return (1);
5207c478bd9Sstevel@tonic-gate p1++;
5217c478bd9Sstevel@tonic-gate p2++;
5227c478bd9Sstevel@tonic-gate seq1 = atoi(p1);
5237c478bd9Sstevel@tonic-gate seq2 = atoi(p2);
5247c478bd9Sstevel@tonic-gate return (seq1 - seq2);
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate * Print usage info and exit.
5307c478bd9Sstevel@tonic-gate */
531032624d5Sbasabi static void
usage(void)532032624d5Sbasabi usage(void)
5337c478bd9Sstevel@tonic-gate {
5347c478bd9Sstevel@tonic-gate fprintf(stderr, "usage: atq [-c] [-n] [name ...]\n");
5357c478bd9Sstevel@tonic-gate exit(1);
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate
538032624d5Sbasabi static void
aterror(char * msg)539032624d5Sbasabi aterror(char *msg)
5407c478bd9Sstevel@tonic-gate {
5417c478bd9Sstevel@tonic-gate fprintf(stderr, "atq: %s\n", msg);
5427c478bd9Sstevel@tonic-gate }
5437c478bd9Sstevel@tonic-gate
544032624d5Sbasabi static void
atperror(char * msg)545032624d5Sbasabi atperror(char *msg)
5467c478bd9Sstevel@tonic-gate {
5477c478bd9Sstevel@tonic-gate fprintf(stderr, "atq: %s: %s\n", msg, errmsg(errno));
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate
550032624d5Sbasabi static void
atabort(char * msg)551032624d5Sbasabi atabort(char *msg)
5527c478bd9Sstevel@tonic-gate {
5537c478bd9Sstevel@tonic-gate aterror(msg);
5547c478bd9Sstevel@tonic-gate exit(1);
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate
557032624d5Sbasabi static void
atabortperror(char * msg)558032624d5Sbasabi atabortperror(char *msg)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate atperror(msg);
5617c478bd9Sstevel@tonic-gate exit(1);
5627c478bd9Sstevel@tonic-gate }
563