#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 <stdlib.h>
#include <string.h>
#include "cron.h"
extern char *errmsg();
extern char *strchr();
static char *mthnames[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec",
};
int numentries;
int namewanted = 0;
struct dirent **queue;
#define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)"
#define NOTALLOWED "you are not authorized to use at. Sorry."
static void atabortperror(char *msg);
static void atabort(char *msg);
static void aterror(char *msg);
static void atperror(char *msg);
static void usage(void);
static void printjobname(char *file);
static void printdate(char *filename);
static void printrank(int n);
static void printqueue(uid_t *uidlist, int nuids);
int
main(int argc, char **argv)
{
struct passwd *pp;
struct passwd pr;
int i;
int cflag = 0;
int nflag = 0;
extern int creation();
extern int execution();
int filewanted();
int countfiles();
uid_t *uidlist = NULL;
int argnum = 0;
int badarg = 0;
char *c;
--argc, ++argv;
(void) setlocale(LC_ALL, "");
pp = getpwuid(getuid());
if (pp == NULL)
atabort(INVALIDUSER);
if (!allowed(pp->pw_name, ATALLOW, ATDENY))
atabort(NOTALLOWED);
pr.pw_uid = pp->pw_uid;
pr.pw_name = pp->pw_name;
while (argc > 0 && **argv == '-') {
(*argv)++;
while (**argv) {
switch (*(*argv)++) {
case 'c' : cflag++;
break;
case 'n' : nflag++;
break;
default : usage();
}
}
--argc, ++argv;
}
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 (cron_admin(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 (!cron_admin(pr.pw_name)) {
++namewanted;
argnum = 1;
if ((uidlist = (uid_t *)malloc(sizeof (uid_t))) == NULL)
atabortperror("can't allocate list of users");
*uidlist = pr.pw_uid;
}
if (chdir(ATDIR) == -1)
atabortperror(ATDIR);
if ((numentries = scandir(".", &queue, filewanted,
(cflag) ? creation : execution)) < 0)
atabortperror(ATDIR);
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);
return (0);
}
int
countfiles(uid_t *uidlist, int nuids)
{
int i, j;
int entryfound;
int numfiles = 0;
uid_t *ptr;
struct stat stbuf;
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);
}
static void
printqueue(uid_t *uidlist, int nuids)
{
int i, j;
int rank;
int entryfound;
char *getname();
uid_t *ptr;
struct stat stbuf;
char curqueue;
char lastqueue;
printf(" Rank Execution Date Owner Job "
"Queue Job Name\n");
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;
}
uid_t
getid(char *name)
{
struct passwd *pwdinfo;
if ((pwdinfo = getpwnam(name)) == 0)
return ((uid_t)-1);
return (pwdinfo->pw_uid);
}
char *
getname(uid_t uid)
{
struct passwd *pwdinfo;
if ((pwdinfo = getpwuid(uid)) == 0)
return ("???");
return (pwdinfo->pw_name);
}
static void
printrank(int 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]);
}
static void
printdate(char *filename)
{
time_t jobdate;
struct tm *unpackeddate;
char date[19];
jobdate = num(&filename);
unpackeddate = localtime(&jobdate);
unpackeddate->tm_year += 1900;
snprintf(date, sizeof (date), "%3s %2d, %4d %02d:%02d",
mthnames[unpackeddate->tm_mon],
unpackeddate->tm_mday, unpackeddate->tm_year,
unpackeddate->tm_hour, unpackeddate->tm_min);
printf("%-21.18s", date);
}
static void
printjobname(char *file)
{
char *ptr;
char jobname[28];
FILE *filename;
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;
}
fscanf(filename, "%*[^\n]\n");
if (fscanf(filename, ": jobname: %27s%*[^\n]\n", jobname) != 1) {
printf("%.27s\n", "???");
fclose(filename);
return;
}
fclose(filename);
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);
}
int
creation(struct dirent **d1, struct dirent **d2)
{
char *p1, *p2;
int i;
struct stat stbuf1, stbuf2;
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);
}
int
execution(struct dirent **d1, struct dirent **d2)
{
char *p1, *p2;
int i;
char *name1, *name2;
time_t time1, time2;
int seq1, seq2;
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);
}
static void
usage(void)
{
fprintf(stderr, "usage: atq [-c] [-n] [name ...]\n");
exit(1);
}
static void
aterror(char *msg)
{
fprintf(stderr, "atq: %s\n", msg);
}
static void
atperror(char *msg)
{
fprintf(stderr, "atq: %s: %s\n", msg, errmsg(errno));
}
static void
atabort(char *msg)
{
aterror(msg);
exit(1);
}
static void
atabortperror(char *msg)
{
atperror(msg);
exit(1);
}