diff options
Diffstat (limited to 'usr/src/cmd/cron/atq.c')
| -rw-r--r-- | usr/src/cmd/cron/atq.c | 562 |
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); +} |
