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