summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cron/atq.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/cron/atq.c')
-rw-r--r--usr/src/cmd/cron/atq.c562
1 files changed, 562 insertions, 0 deletions
diff --git a/usr/src/cmd/cron/atq.c b/usr/src/cmd/cron/atq.c
new file mode 100644
index 0000000000..1b3503683d
--- /dev/null
+++ b/usr/src/cmd/cron/atq.c
@@ -0,0 +1,562 @@
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * Copyright 1984-1988, 2002-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */
+
+/*
+ *
+ * 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 defined by ATDIR.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <locale.h>
+#include <errno.h>
+#include "cron.h"
+
+extern char *errmsg();
+extern char *strchr();
+
+/*
+ * Months of the year
+ */
+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; /* print jobs for a certain person */
+struct dirent **queue; /* the queue itself */
+
+#define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)"
+#define NOTALLOWED "you are not authorized to use at. Sorry."
+
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+
+ register struct passwd *pp; /* password file entry pointer */
+ struct passwd pr;
+ register int i;
+ int cflag = 0; /* print in order of creation time */
+ int nflag = 0; /* just print the number of jobs in */
+ /* queue */
+ int usage(); /* print usage info and exit */
+ extern int creation(); /* sort jobs by date of creation */
+ extern int execution(); /* sort jobs by date of execution */
+ int filewanted(); /* should file be included in queue? */
+ int printqueue(); /* print the queue */
+ int countfiles(); /* count the number of files in queue */
+ /* for a given person */
+ uid_t *uidlist = NULL; /* array of spec. owner ID(s) requ. */
+ int argnum = 0; /* number of names passed as arg't */
+ int badarg = 0;
+ char *c;
+
+
+ --argc, ++argv;
+
+ (void) setlocale(LC_ALL, "");
+ pp = getpwuid(getuid());
+ pr.pw_uid = pp->pw_uid;
+ pr.pw_name = pp->pw_name;
+
+ if (pp == NULL)
+ atabort(INVALIDUSER);
+ if (!allowed(pp->pw_name, ATALLOW, ATDENY))
+ atabort(NOTALLOWED);
+
+ /*
+ * Interpret command line flags if they exist.
+ */
+ while (argc > 0 && **argv == '-') {
+ (*argv)++;
+ while (**argv) {
+ switch (*(*argv)++) {
+
+ case 'c' : cflag++;
+ break;
+
+ case 'n' : nflag++;
+ break;
+
+ default : usage();
+
+ }
+ }
+ --argc, ++argv;
+ }
+
+ /*
+ * If a certain name (or names) is requested, set a pointer to the
+ * beginning of the list.
+ */
+ if (argc > 0) {
+ ++namewanted;
+ uidlist = (uid_t *)malloc(argc * sizeof (uid_t));
+ if (uidlist == NULL)
+ atabortperror("can't allocate list of users");
+ for (i = 0; i < argc; i++) {
+ if ((chkauthattr(CRONADMIN_AUTH, pr.pw_name)) ||
+ strcmp(pr.pw_name, argv[i]) == 0) {
+ if ((pp = getpwnam(argv[i])) == NULL) {
+ (void) fprintf(stderr,
+ "atq: No such user %s\n", argv[i]);
+ exit(1);
+ }
+ uidlist[argnum] = pp->pw_uid;
+ argnum++;
+ }
+ else
+ badarg++;
+ }
+ if (badarg)
+ if (argnum)
+ printf("Printing queue information only "
+ "for %s:\n", pr.pw_name);
+ else {
+ printf("atq: Non-priviledged user cannot "
+ "request information regarding other "
+ "users\n");
+ exit(1);
+ }
+ } else if (!chkauthattr(CRONADMIN_AUTH, pr.pw_name)) {
+ /* no argument specified and the invoker is not root */
+ ++namewanted;
+ argnum = 1;
+ if ((uidlist = (uid_t *)malloc(sizeof (uid_t))) == NULL)
+ atabortperror("can't allocate list of users");
+ *uidlist = pr.pw_uid;
+ }
+
+ /*
+ * 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)
+ atabortperror(ATDIR);
+ if ((numentries = ascandir(".", &queue, filewanted,
+ (cflag) ? creation : execution)) < 0)
+ atabortperror(ATDIR);
+
+
+ /*
+ * 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
+ * a certain person.
+ * 4) that the person requested doesn't have any files in the
+ * spooling area.
+ *
+ * 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");
+ exit(0);
+ }
+ if (nflag) {
+ printf("%d\n", (namewanted) ?
+ countfiles(uidlist, argnum) : numentries);
+ exit(0);
+ }
+ if ((namewanted) && (countfiles(uidlist, argnum) == 0)) {
+ if (argnum == 1)
+ if (argnum != argc) c = pr.pw_name;
+ else c = *argv;
+ printf("no files for %s.\n", (argnum == 1) ?
+ c : "specified users");
+ exit(0);
+ }
+ printqueue(uidlist, argnum);
+ exit(0);
+}
+
+/*
+ * Count the number of jobs in the spooling area owned by a certain person(s).
+ */
+countfiles(uidlist, nuids)
+uid_t *uidlist;
+int nuids;
+{
+ register int i, j; /* for loop indices */
+ int entryfound; /* found file owned by users */
+ int numfiles = 0; /* number of files owned by a */
+ /* certain person(s) */
+ register uid_t *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) {
+ continue;
+ }
+ ptr = uidlist;
+ entryfound = 0;
+
+ for (j = 0; j < nuids; j++) {
+ if (*ptr == stbuf.st_uid)
+ ++entryfound;
+ ++ptr;
+ }
+ if (entryfound)
+ ++numfiles;
+ }
+ return (numfiles);
+}
+
+/*
+ * Print the queue. If only jobs belonging to a certain person(s) are requested,
+ * only print jobs that belong to that person(s).
+ */
+printqueue(uidlist, nuids)
+uid_t *uidlist;
+int nuids;
+{
+ register int i, j; /* for loop indices */
+ int rank; /* rank of a job */
+ int entryfound; /* found file owned by users */
+ int printrank(); /* print the rank of a job */
+ char *getname();
+ register uid_t *ptr; /* scratch pointer */
+ struct stat stbuf; /* buffer for file stats */
+ char curqueue; /* queue of current job */
+ char lastqueue; /* queue of previous job */
+
+ /*
+ * Print the header for the queue.
+ */
+ printf(" Rank Execution Date Owner Job "
+ "Queue 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.
+ *
+ */
+ lastqueue = '\0';
+ for (i = 0; i < numentries; i++) {
+ if ((stat(queue[i]->d_name, &stbuf)) < 0) {
+ continue;
+ }
+ curqueue = *(strchr(queue[i]->d_name, '.') + 1);
+ if (curqueue != lastqueue) {
+ rank = 1;
+ lastqueue = curqueue;
+ }
+ if (namewanted) {
+ ptr = uidlist;
+ entryfound = 0;
+
+ for (j = 0; j < nuids; j++) {
+ if (*ptr == stbuf.st_uid)
+ ++entryfound;
+ ++ptr;
+ }
+ if (!entryfound)
+ continue;
+ }
+ printrank(rank++);
+ printdate(queue[i]->d_name);
+ printf("%-10s ", getname(stbuf.st_uid));
+ printf("%-14s ", queue[i]->d_name);
+ printf(" %c", curqueue);
+ printjobname(queue[i]->d_name);
+ }
+ ++ptr;
+}
+
+/*
+ * Get the uid of a person using his/her login name. Return -1 if no
+ * such account name exists.
+ */
+uid_t
+getid(name)
+char *name;
+{
+
+ struct passwd *pwdinfo; /* password info structure */
+
+
+ if ((pwdinfo = getpwnam(name)) == 0)
+ return ((uid_t)-1);
+
+ return (pwdinfo->pw_uid);
+}
+
+/*
+ * Get the full login name of a person using his/her user id.
+ */
+char *
+getname(uid)
+uid_t uid;
+{
+ register struct passwd *pwdinfo; /* password info structure */
+
+
+ if ((pwdinfo = getpwuid(uid)) == 0)
+ return ("???");
+ return (pwdinfo->pw_name);
+}
+
+/*
+ * Print the rank of a job. (I've got to admit it, I stole it from "lpq")
+ */
+static
+printrank(n)
+{
+ static char *r[] = {
+ "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
+ };
+
+ if ((n/10) == 1)
+ printf("%3d%-5s", n, "th");
+ else
+ printf("%3d%-5s", n, r[n%10]);
+}
+
+/*
+ * Print the date that a job is to be executed. This takes some manipulation
+ * of the file name.
+ */
+printdate(filename)
+char *filename;
+{
+ time_t jobdate;
+ extern time_t num();
+ register struct tm *unpackeddate;
+ char date[18]; /* reformatted execution date */
+
+ /*
+ * Convert the file name to a date.
+ */
+ jobdate = num(&filename);
+ unpackeddate = localtime(&jobdate);
+
+ /* years since 1900 + base century 1900 */
+ unpackeddate->tm_year += 1900;
+ /*
+ * Format the execution date of a job.
+ */
+ sprintf(date, "%3s %2d, %4d %02d:%02d", mthnames[unpackeddate->tm_mon],
+ unpackeddate->tm_mday, unpackeddate->tm_year,
+ unpackeddate->tm_hour, unpackeddate->tm_min);
+
+ /*
+ * Print the date the job will be executed.
+ */
+ printf("%-21.18s", date);
+}
+
+/*
+ * 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 "???".
+ */
+printjobname(file)
+char *file;
+{
+ char *ptr; /* scratch pointer */
+ char jobname[28]; /* the job name */
+ FILE *filename; /* job file in spooling area */
+
+ /*
+ * Open the job file and grab the third line.
+ */
+ printf(" ");
+
+ if ((filename = fopen(file, "r")) == NULL) {
+ printf("%.27s\n", "???");
+ (void) fprintf(stderr, "atq: Can't open job file %s: %s\n",
+ file, errmsg(errno));
+ return;
+ }
+ /*
+ * Skip over the first and second lines.
+ */
+ fscanf(filename, "%*[^\n]\n");
+
+ /*
+ * Now get the job name.
+ */
+ if (fscanf(filename, ": jobname: %27s%*[^\n]\n", jobname) != 1) {
+ printf("%.27s\n", "???");
+ fclose(filename);
+ return;
+ }
+ fclose(filename);
+
+ /*
+ * Put a pointer at the begining of the line and remove the basename
+ * from the job file.
+ */
+ ptr = jobname;
+ if ((ptr = (char *)strrchr(jobname, '/')) != 0)
+ ++ptr;
+ else
+ ptr = jobname;
+
+ if (strlen(ptr) > 23)
+ printf("%.23s ...\n", ptr);
+ else
+ printf("%.27s\n", ptr);
+}
+
+
+
+/*
+ * Sort files by queue, time of creation, and sequence. (used by "ascandir")
+ */
+creation(d1, d2)
+struct dirent **d1, **d2;
+{
+ register char *p1, *p2;
+ register int i;
+ struct stat stbuf1, stbuf2;
+ register int seq1, seq2;
+
+ if ((p1 = strchr((*d1)->d_name, '.')) == NULL)
+ return (0);
+ if ((p2 = strchr((*d2)->d_name, '.')) == NULL)
+ return (0);
+ p1++;
+ p2++;
+ if ((i = *p1++ - *p2++) != 0)
+ return (i);
+
+ if (stat((*d1)->d_name, &stbuf1) < 0)
+ return (0);
+
+ if (stat((*d2)->d_name, &stbuf2) < 0)
+ return (0);
+
+ if (stbuf1.st_ctime < stbuf2.st_ctime)
+ return (-1);
+ else if (stbuf1.st_ctime > stbuf2.st_ctime)
+ return (1);
+ p1++;
+ p2++;
+ seq1 = atoi(p1);
+ seq2 = atoi(p2);
+ return (seq1 - seq2);
+}
+
+/*
+ * Sort files by queue, time of execution, and sequence. (used by "ascandir")
+ */
+execution(d1, d2)
+struct dirent **d1, **d2;
+{
+ register char *p1, *p2;
+ register int i;
+ char *name1, *name2;
+ register time_t time1, time2;
+ register int seq1, seq2;
+ extern time_t num();
+
+ name1 = (*d1)->d_name;
+ name2 = (*d2)->d_name;
+ if ((p1 = strchr(name1, '.')) == NULL)
+ return (1);
+ if ((p2 = strchr(name2, '.')) == NULL)
+ return (1);
+ p1++;
+ p2++;
+ if ((i = *p1++ - *p2++) != 0)
+ return (i);
+
+ time1 = num(&name1);
+ time2 = num(&name2);
+
+ if (time1 < time2)
+ return (-1);
+ else if (time1 > time2)
+ return (1);
+ p1++;
+ p2++;
+ seq1 = atoi(p1);
+ seq2 = atoi(p2);
+ return (seq1 - seq2);
+}
+
+
+/*
+ * Print usage info and exit.
+ */
+usage()
+{
+ fprintf(stderr, "usage: atq [-c] [-n] [name ...]\n");
+ exit(1);
+}
+
+aterror(msg)
+ char *msg;
+{
+ fprintf(stderr, "atq: %s\n", msg);
+}
+
+atperror(msg)
+ char *msg;
+{
+ fprintf(stderr, "atq: %s: %s\n", msg, errmsg(errno));
+}
+
+atabort(msg)
+ char *msg;
+{
+ aterror(msg);
+ exit(1);
+}
+
+atabortperror(msg)
+ char *msg;
+{
+ atperror(msg);
+ exit(1);
+}