1*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 2*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 3*7c478bd9Sstevel@tonic-gate 4*7c478bd9Sstevel@tonic-gate 5*7c478bd9Sstevel@tonic-gate /* 6*7c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 7*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 8*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 9*7c478bd9Sstevel@tonic-gate */ 10*7c478bd9Sstevel@tonic-gate 11*7c478bd9Sstevel@tonic-gate /* 12*7c478bd9Sstevel@tonic-gate * Copyright 1984-1988, 2002-2003 Sun Microsystems, Inc. All rights reserved. 13*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 14*7c478bd9Sstevel@tonic-gate */ 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */ 17*7c478bd9Sstevel@tonic-gate 18*7c478bd9Sstevel@tonic-gate /* 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * Synopsis: atq [ -c ] [ -n ] [ name ... ] 21*7c478bd9Sstevel@tonic-gate * 22*7c478bd9Sstevel@tonic-gate * 23*7c478bd9Sstevel@tonic-gate * Print the queue of files waiting to be executed. These files 24*7c478bd9Sstevel@tonic-gate * were created by using the "at" command and are located in the 25*7c478bd9Sstevel@tonic-gate * directory defined by ATDIR. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <stdio.h> 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 31*7c478bd9Sstevel@tonic-gate #include <dirent.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 33*7c478bd9Sstevel@tonic-gate #include <time.h> 34*7c478bd9Sstevel@tonic-gate #include <pwd.h> 35*7c478bd9Sstevel@tonic-gate #include <ctype.h> 36*7c478bd9Sstevel@tonic-gate #include <unistd.h> 37*7c478bd9Sstevel@tonic-gate #include <locale.h> 38*7c478bd9Sstevel@tonic-gate #include <errno.h> 39*7c478bd9Sstevel@tonic-gate #include "cron.h" 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate extern char *errmsg(); 42*7c478bd9Sstevel@tonic-gate extern char *strchr(); 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate /* 45*7c478bd9Sstevel@tonic-gate * Months of the year 46*7c478bd9Sstevel@tonic-gate */ 47*7c478bd9Sstevel@tonic-gate static char *mthnames[12] = { 48*7c478bd9Sstevel@tonic-gate "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", 49*7c478bd9Sstevel@tonic-gate "Aug", "Sep", "Oct", "Nov", "Dec", 50*7c478bd9Sstevel@tonic-gate }; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate int numentries; /* number of entries in spooling area */ 53*7c478bd9Sstevel@tonic-gate int namewanted = 0; /* print jobs for a certain person */ 54*7c478bd9Sstevel@tonic-gate struct dirent **queue; /* the queue itself */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)" 57*7c478bd9Sstevel@tonic-gate #define NOTALLOWED "you are not authorized to use at. Sorry." 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate main(argc, argv) 61*7c478bd9Sstevel@tonic-gate int argc; 62*7c478bd9Sstevel@tonic-gate char **argv; 63*7c478bd9Sstevel@tonic-gate { 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate register struct passwd *pp; /* password file entry pointer */ 66*7c478bd9Sstevel@tonic-gate struct passwd pr; 67*7c478bd9Sstevel@tonic-gate register int i; 68*7c478bd9Sstevel@tonic-gate int cflag = 0; /* print in order of creation time */ 69*7c478bd9Sstevel@tonic-gate int nflag = 0; /* just print the number of jobs in */ 70*7c478bd9Sstevel@tonic-gate /* queue */ 71*7c478bd9Sstevel@tonic-gate int usage(); /* print usage info and exit */ 72*7c478bd9Sstevel@tonic-gate extern int creation(); /* sort jobs by date of creation */ 73*7c478bd9Sstevel@tonic-gate extern int execution(); /* sort jobs by date of execution */ 74*7c478bd9Sstevel@tonic-gate int filewanted(); /* should file be included in queue? */ 75*7c478bd9Sstevel@tonic-gate int printqueue(); /* print the queue */ 76*7c478bd9Sstevel@tonic-gate int countfiles(); /* count the number of files in queue */ 77*7c478bd9Sstevel@tonic-gate /* for a given person */ 78*7c478bd9Sstevel@tonic-gate uid_t *uidlist = NULL; /* array of spec. owner ID(s) requ. */ 79*7c478bd9Sstevel@tonic-gate int argnum = 0; /* number of names passed as arg't */ 80*7c478bd9Sstevel@tonic-gate int badarg = 0; 81*7c478bd9Sstevel@tonic-gate char *c; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate --argc, ++argv; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 87*7c478bd9Sstevel@tonic-gate pp = getpwuid(getuid()); 88*7c478bd9Sstevel@tonic-gate pr.pw_uid = pp->pw_uid; 89*7c478bd9Sstevel@tonic-gate pr.pw_name = pp->pw_name; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate if (pp == NULL) 92*7c478bd9Sstevel@tonic-gate atabort(INVALIDUSER); 93*7c478bd9Sstevel@tonic-gate if (!allowed(pp->pw_name, ATALLOW, ATDENY)) 94*7c478bd9Sstevel@tonic-gate atabort(NOTALLOWED); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * Interpret command line flags if they exist. 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate while (argc > 0 && **argv == '-') { 100*7c478bd9Sstevel@tonic-gate (*argv)++; 101*7c478bd9Sstevel@tonic-gate while (**argv) { 102*7c478bd9Sstevel@tonic-gate switch (*(*argv)++) { 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate case 'c' : cflag++; 105*7c478bd9Sstevel@tonic-gate break; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate case 'n' : nflag++; 108*7c478bd9Sstevel@tonic-gate break; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate default : usage(); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate --argc, ++argv; 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate /* 118*7c478bd9Sstevel@tonic-gate * If a certain name (or names) is requested, set a pointer to the 119*7c478bd9Sstevel@tonic-gate * beginning of the list. 120*7c478bd9Sstevel@tonic-gate */ 121*7c478bd9Sstevel@tonic-gate if (argc > 0) { 122*7c478bd9Sstevel@tonic-gate ++namewanted; 123*7c478bd9Sstevel@tonic-gate uidlist = (uid_t *)malloc(argc * sizeof (uid_t)); 124*7c478bd9Sstevel@tonic-gate if (uidlist == NULL) 125*7c478bd9Sstevel@tonic-gate atabortperror("can't allocate list of users"); 126*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 127*7c478bd9Sstevel@tonic-gate if ((chkauthattr(CRONADMIN_AUTH, pr.pw_name)) || 128*7c478bd9Sstevel@tonic-gate strcmp(pr.pw_name, argv[i]) == 0) { 129*7c478bd9Sstevel@tonic-gate if ((pp = getpwnam(argv[i])) == NULL) { 130*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 131*7c478bd9Sstevel@tonic-gate "atq: No such user %s\n", argv[i]); 132*7c478bd9Sstevel@tonic-gate exit(1); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate uidlist[argnum] = pp->pw_uid; 135*7c478bd9Sstevel@tonic-gate argnum++; 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate else 138*7c478bd9Sstevel@tonic-gate badarg++; 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate if (badarg) 141*7c478bd9Sstevel@tonic-gate if (argnum) 142*7c478bd9Sstevel@tonic-gate printf("Printing queue information only " 143*7c478bd9Sstevel@tonic-gate "for %s:\n", pr.pw_name); 144*7c478bd9Sstevel@tonic-gate else { 145*7c478bd9Sstevel@tonic-gate printf("atq: Non-priviledged user cannot " 146*7c478bd9Sstevel@tonic-gate "request information regarding other " 147*7c478bd9Sstevel@tonic-gate "users\n"); 148*7c478bd9Sstevel@tonic-gate exit(1); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate } else if (!chkauthattr(CRONADMIN_AUTH, pr.pw_name)) { 151*7c478bd9Sstevel@tonic-gate /* no argument specified and the invoker is not root */ 152*7c478bd9Sstevel@tonic-gate ++namewanted; 153*7c478bd9Sstevel@tonic-gate argnum = 1; 154*7c478bd9Sstevel@tonic-gate if ((uidlist = (uid_t *)malloc(sizeof (uid_t))) == NULL) 155*7c478bd9Sstevel@tonic-gate atabortperror("can't allocate list of users"); 156*7c478bd9Sstevel@tonic-gate *uidlist = pr.pw_uid; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate /* 160*7c478bd9Sstevel@tonic-gate * Move to the spooling area and scan the directory, placing the 161*7c478bd9Sstevel@tonic-gate * files in the queue structure. The queue comes back sorted by 162*7c478bd9Sstevel@tonic-gate * execution time or creation time. 163*7c478bd9Sstevel@tonic-gate */ 164*7c478bd9Sstevel@tonic-gate if (chdir(ATDIR) == -1) 165*7c478bd9Sstevel@tonic-gate atabortperror(ATDIR); 166*7c478bd9Sstevel@tonic-gate if ((numentries = ascandir(".", &queue, filewanted, 167*7c478bd9Sstevel@tonic-gate (cflag) ? creation : execution)) < 0) 168*7c478bd9Sstevel@tonic-gate atabortperror(ATDIR); 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * Either print a message stating: 173*7c478bd9Sstevel@tonic-gate * 174*7c478bd9Sstevel@tonic-gate * 1) that the spooling area is empty. 175*7c478bd9Sstevel@tonic-gate * 2) the number of jobs in the spooling area. 176*7c478bd9Sstevel@tonic-gate * 3) the number of jobs in the spooling area belonging to 177*7c478bd9Sstevel@tonic-gate * a certain person. 178*7c478bd9Sstevel@tonic-gate * 4) that the person requested doesn't have any files in the 179*7c478bd9Sstevel@tonic-gate * spooling area. 180*7c478bd9Sstevel@tonic-gate * 181*7c478bd9Sstevel@tonic-gate * or send the queue off to "printqueue" for printing. 182*7c478bd9Sstevel@tonic-gate * 183*7c478bd9Sstevel@tonic-gate * This whole process might seem a bit elaborate, but it's worthwhile 184*7c478bd9Sstevel@tonic-gate * to print some informative messages for the user. 185*7c478bd9Sstevel@tonic-gate * 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate if ((numentries == 0) && (!nflag)) { 188*7c478bd9Sstevel@tonic-gate printf("no files in queue.\n"); 189*7c478bd9Sstevel@tonic-gate exit(0); 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate if (nflag) { 192*7c478bd9Sstevel@tonic-gate printf("%d\n", (namewanted) ? 193*7c478bd9Sstevel@tonic-gate countfiles(uidlist, argnum) : numentries); 194*7c478bd9Sstevel@tonic-gate exit(0); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate if ((namewanted) && (countfiles(uidlist, argnum) == 0)) { 197*7c478bd9Sstevel@tonic-gate if (argnum == 1) 198*7c478bd9Sstevel@tonic-gate if (argnum != argc) c = pr.pw_name; 199*7c478bd9Sstevel@tonic-gate else c = *argv; 200*7c478bd9Sstevel@tonic-gate printf("no files for %s.\n", (argnum == 1) ? 201*7c478bd9Sstevel@tonic-gate c : "specified users"); 202*7c478bd9Sstevel@tonic-gate exit(0); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate printqueue(uidlist, argnum); 205*7c478bd9Sstevel@tonic-gate exit(0); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * Count the number of jobs in the spooling area owned by a certain person(s). 210*7c478bd9Sstevel@tonic-gate */ 211*7c478bd9Sstevel@tonic-gate countfiles(uidlist, nuids) 212*7c478bd9Sstevel@tonic-gate uid_t *uidlist; 213*7c478bd9Sstevel@tonic-gate int nuids; 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate register int i, j; /* for loop indices */ 216*7c478bd9Sstevel@tonic-gate int entryfound; /* found file owned by users */ 217*7c478bd9Sstevel@tonic-gate int numfiles = 0; /* number of files owned by a */ 218*7c478bd9Sstevel@tonic-gate /* certain person(s) */ 219*7c478bd9Sstevel@tonic-gate register uid_t *ptr; /* scratch pointer */ 220*7c478bd9Sstevel@tonic-gate struct stat stbuf; /* buffer for file stats */ 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * For each file in the queue, see if the user(s) own the file. We 225*7c478bd9Sstevel@tonic-gate * have to use "entryfound" (rather than simply incrementing "numfiles") 226*7c478bd9Sstevel@tonic-gate * so that if a person's name appears twice on the command line we 227*7c478bd9Sstevel@tonic-gate * don't double the number of files owned by him/her. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate for (i = 0; i < numentries; i++) { 230*7c478bd9Sstevel@tonic-gate if ((stat(queue[i]->d_name, &stbuf)) < 0) { 231*7c478bd9Sstevel@tonic-gate continue; 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate ptr = uidlist; 234*7c478bd9Sstevel@tonic-gate entryfound = 0; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate for (j = 0; j < nuids; j++) { 237*7c478bd9Sstevel@tonic-gate if (*ptr == stbuf.st_uid) 238*7c478bd9Sstevel@tonic-gate ++entryfound; 239*7c478bd9Sstevel@tonic-gate ++ptr; 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate if (entryfound) 242*7c478bd9Sstevel@tonic-gate ++numfiles; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate return (numfiles); 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* 248*7c478bd9Sstevel@tonic-gate * Print the queue. If only jobs belonging to a certain person(s) are requested, 249*7c478bd9Sstevel@tonic-gate * only print jobs that belong to that person(s). 250*7c478bd9Sstevel@tonic-gate */ 251*7c478bd9Sstevel@tonic-gate printqueue(uidlist, nuids) 252*7c478bd9Sstevel@tonic-gate uid_t *uidlist; 253*7c478bd9Sstevel@tonic-gate int nuids; 254*7c478bd9Sstevel@tonic-gate { 255*7c478bd9Sstevel@tonic-gate register int i, j; /* for loop indices */ 256*7c478bd9Sstevel@tonic-gate int rank; /* rank of a job */ 257*7c478bd9Sstevel@tonic-gate int entryfound; /* found file owned by users */ 258*7c478bd9Sstevel@tonic-gate int printrank(); /* print the rank of a job */ 259*7c478bd9Sstevel@tonic-gate char *getname(); 260*7c478bd9Sstevel@tonic-gate register uid_t *ptr; /* scratch pointer */ 261*7c478bd9Sstevel@tonic-gate struct stat stbuf; /* buffer for file stats */ 262*7c478bd9Sstevel@tonic-gate char curqueue; /* queue of current job */ 263*7c478bd9Sstevel@tonic-gate char lastqueue; /* queue of previous job */ 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * Print the header for the queue. 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate printf(" Rank Execution Date Owner Job " 269*7c478bd9Sstevel@tonic-gate "Queue Job Name\n"); 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * Print the queue. If a certain name(s) was requested, print only jobs 273*7c478bd9Sstevel@tonic-gate * belonging to that person(s), otherwise print the entire queue. 274*7c478bd9Sstevel@tonic-gate * Once again, we have to use "entryfound" (rather than simply 275*7c478bd9Sstevel@tonic-gate * comparing each command line argument) so that if a person's name 276*7c478bd9Sstevel@tonic-gate * appears twice we don't print each file owned by him/her twice. 277*7c478bd9Sstevel@tonic-gate * 278*7c478bd9Sstevel@tonic-gate * 279*7c478bd9Sstevel@tonic-gate * "printrank", "printdate", and "printjobname" all take existing 280*7c478bd9Sstevel@tonic-gate * data and display it in a friendly manner. 281*7c478bd9Sstevel@tonic-gate * 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate lastqueue = '\0'; 284*7c478bd9Sstevel@tonic-gate for (i = 0; i < numentries; i++) { 285*7c478bd9Sstevel@tonic-gate if ((stat(queue[i]->d_name, &stbuf)) < 0) { 286*7c478bd9Sstevel@tonic-gate continue; 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate curqueue = *(strchr(queue[i]->d_name, '.') + 1); 289*7c478bd9Sstevel@tonic-gate if (curqueue != lastqueue) { 290*7c478bd9Sstevel@tonic-gate rank = 1; 291*7c478bd9Sstevel@tonic-gate lastqueue = curqueue; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate if (namewanted) { 294*7c478bd9Sstevel@tonic-gate ptr = uidlist; 295*7c478bd9Sstevel@tonic-gate entryfound = 0; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate for (j = 0; j < nuids; j++) { 298*7c478bd9Sstevel@tonic-gate if (*ptr == stbuf.st_uid) 299*7c478bd9Sstevel@tonic-gate ++entryfound; 300*7c478bd9Sstevel@tonic-gate ++ptr; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate if (!entryfound) 303*7c478bd9Sstevel@tonic-gate continue; 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate printrank(rank++); 306*7c478bd9Sstevel@tonic-gate printdate(queue[i]->d_name); 307*7c478bd9Sstevel@tonic-gate printf("%-10s ", getname(stbuf.st_uid)); 308*7c478bd9Sstevel@tonic-gate printf("%-14s ", queue[i]->d_name); 309*7c478bd9Sstevel@tonic-gate printf(" %c", curqueue); 310*7c478bd9Sstevel@tonic-gate printjobname(queue[i]->d_name); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate ++ptr; 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * Get the uid of a person using his/her login name. Return -1 if no 317*7c478bd9Sstevel@tonic-gate * such account name exists. 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate uid_t 320*7c478bd9Sstevel@tonic-gate getid(name) 321*7c478bd9Sstevel@tonic-gate char *name; 322*7c478bd9Sstevel@tonic-gate { 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate struct passwd *pwdinfo; /* password info structure */ 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate if ((pwdinfo = getpwnam(name)) == 0) 328*7c478bd9Sstevel@tonic-gate return ((uid_t)-1); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate return (pwdinfo->pw_uid); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * Get the full login name of a person using his/her user id. 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate char * 337*7c478bd9Sstevel@tonic-gate getname(uid) 338*7c478bd9Sstevel@tonic-gate uid_t uid; 339*7c478bd9Sstevel@tonic-gate { 340*7c478bd9Sstevel@tonic-gate register struct passwd *pwdinfo; /* password info structure */ 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate if ((pwdinfo = getpwuid(uid)) == 0) 344*7c478bd9Sstevel@tonic-gate return ("???"); 345*7c478bd9Sstevel@tonic-gate return (pwdinfo->pw_name); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * Print the rank of a job. (I've got to admit it, I stole it from "lpq") 350*7c478bd9Sstevel@tonic-gate */ 351*7c478bd9Sstevel@tonic-gate static 352*7c478bd9Sstevel@tonic-gate printrank(n) 353*7c478bd9Sstevel@tonic-gate { 354*7c478bd9Sstevel@tonic-gate static char *r[] = { 355*7c478bd9Sstevel@tonic-gate "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 356*7c478bd9Sstevel@tonic-gate }; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate if ((n/10) == 1) 359*7c478bd9Sstevel@tonic-gate printf("%3d%-5s", n, "th"); 360*7c478bd9Sstevel@tonic-gate else 361*7c478bd9Sstevel@tonic-gate printf("%3d%-5s", n, r[n%10]); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate /* 365*7c478bd9Sstevel@tonic-gate * Print the date that a job is to be executed. This takes some manipulation 366*7c478bd9Sstevel@tonic-gate * of the file name. 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate printdate(filename) 369*7c478bd9Sstevel@tonic-gate char *filename; 370*7c478bd9Sstevel@tonic-gate { 371*7c478bd9Sstevel@tonic-gate time_t jobdate; 372*7c478bd9Sstevel@tonic-gate extern time_t num(); 373*7c478bd9Sstevel@tonic-gate register struct tm *unpackeddate; 374*7c478bd9Sstevel@tonic-gate char date[18]; /* reformatted execution date */ 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * Convert the file name to a date. 378*7c478bd9Sstevel@tonic-gate */ 379*7c478bd9Sstevel@tonic-gate jobdate = num(&filename); 380*7c478bd9Sstevel@tonic-gate unpackeddate = localtime(&jobdate); 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* years since 1900 + base century 1900 */ 383*7c478bd9Sstevel@tonic-gate unpackeddate->tm_year += 1900; 384*7c478bd9Sstevel@tonic-gate /* 385*7c478bd9Sstevel@tonic-gate * Format the execution date of a job. 386*7c478bd9Sstevel@tonic-gate */ 387*7c478bd9Sstevel@tonic-gate sprintf(date, "%3s %2d, %4d %02d:%02d", mthnames[unpackeddate->tm_mon], 388*7c478bd9Sstevel@tonic-gate unpackeddate->tm_mday, unpackeddate->tm_year, 389*7c478bd9Sstevel@tonic-gate unpackeddate->tm_hour, unpackeddate->tm_min); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* 392*7c478bd9Sstevel@tonic-gate * Print the date the job will be executed. 393*7c478bd9Sstevel@tonic-gate */ 394*7c478bd9Sstevel@tonic-gate printf("%-21.18s", date); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * Print a job name. If the old "at" has been used to create the spoolfile, 399*7c478bd9Sstevel@tonic-gate * the three line header that the new version of "at" puts in the spoolfile. 400*7c478bd9Sstevel@tonic-gate * Thus, we just print "???". 401*7c478bd9Sstevel@tonic-gate */ 402*7c478bd9Sstevel@tonic-gate printjobname(file) 403*7c478bd9Sstevel@tonic-gate char *file; 404*7c478bd9Sstevel@tonic-gate { 405*7c478bd9Sstevel@tonic-gate char *ptr; /* scratch pointer */ 406*7c478bd9Sstevel@tonic-gate char jobname[28]; /* the job name */ 407*7c478bd9Sstevel@tonic-gate FILE *filename; /* job file in spooling area */ 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * Open the job file and grab the third line. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate printf(" "); 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate if ((filename = fopen(file, "r")) == NULL) { 415*7c478bd9Sstevel@tonic-gate printf("%.27s\n", "???"); 416*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "atq: Can't open job file %s: %s\n", 417*7c478bd9Sstevel@tonic-gate file, errmsg(errno)); 418*7c478bd9Sstevel@tonic-gate return; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * Skip over the first and second lines. 422*7c478bd9Sstevel@tonic-gate */ 423*7c478bd9Sstevel@tonic-gate fscanf(filename, "%*[^\n]\n"); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate /* 426*7c478bd9Sstevel@tonic-gate * Now get the job name. 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate if (fscanf(filename, ": jobname: %27s%*[^\n]\n", jobname) != 1) { 429*7c478bd9Sstevel@tonic-gate printf("%.27s\n", "???"); 430*7c478bd9Sstevel@tonic-gate fclose(filename); 431*7c478bd9Sstevel@tonic-gate return; 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate fclose(filename); 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate /* 436*7c478bd9Sstevel@tonic-gate * Put a pointer at the begining of the line and remove the basename 437*7c478bd9Sstevel@tonic-gate * from the job file. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate ptr = jobname; 440*7c478bd9Sstevel@tonic-gate if ((ptr = (char *)strrchr(jobname, '/')) != 0) 441*7c478bd9Sstevel@tonic-gate ++ptr; 442*7c478bd9Sstevel@tonic-gate else 443*7c478bd9Sstevel@tonic-gate ptr = jobname; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate if (strlen(ptr) > 23) 446*7c478bd9Sstevel@tonic-gate printf("%.23s ...\n", ptr); 447*7c478bd9Sstevel@tonic-gate else 448*7c478bd9Sstevel@tonic-gate printf("%.27s\n", ptr); 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * Sort files by queue, time of creation, and sequence. (used by "ascandir") 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate creation(d1, d2) 457*7c478bd9Sstevel@tonic-gate struct dirent **d1, **d2; 458*7c478bd9Sstevel@tonic-gate { 459*7c478bd9Sstevel@tonic-gate register char *p1, *p2; 460*7c478bd9Sstevel@tonic-gate register int i; 461*7c478bd9Sstevel@tonic-gate struct stat stbuf1, stbuf2; 462*7c478bd9Sstevel@tonic-gate register int seq1, seq2; 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate if ((p1 = strchr((*d1)->d_name, '.')) == NULL) 465*7c478bd9Sstevel@tonic-gate return (0); 466*7c478bd9Sstevel@tonic-gate if ((p2 = strchr((*d2)->d_name, '.')) == NULL) 467*7c478bd9Sstevel@tonic-gate return (0); 468*7c478bd9Sstevel@tonic-gate p1++; 469*7c478bd9Sstevel@tonic-gate p2++; 470*7c478bd9Sstevel@tonic-gate if ((i = *p1++ - *p2++) != 0) 471*7c478bd9Sstevel@tonic-gate return (i); 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate if (stat((*d1)->d_name, &stbuf1) < 0) 474*7c478bd9Sstevel@tonic-gate return (0); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate if (stat((*d2)->d_name, &stbuf2) < 0) 477*7c478bd9Sstevel@tonic-gate return (0); 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if (stbuf1.st_ctime < stbuf2.st_ctime) 480*7c478bd9Sstevel@tonic-gate return (-1); 481*7c478bd9Sstevel@tonic-gate else if (stbuf1.st_ctime > stbuf2.st_ctime) 482*7c478bd9Sstevel@tonic-gate return (1); 483*7c478bd9Sstevel@tonic-gate p1++; 484*7c478bd9Sstevel@tonic-gate p2++; 485*7c478bd9Sstevel@tonic-gate seq1 = atoi(p1); 486*7c478bd9Sstevel@tonic-gate seq2 = atoi(p2); 487*7c478bd9Sstevel@tonic-gate return (seq1 - seq2); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate /* 491*7c478bd9Sstevel@tonic-gate * Sort files by queue, time of execution, and sequence. (used by "ascandir") 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate execution(d1, d2) 494*7c478bd9Sstevel@tonic-gate struct dirent **d1, **d2; 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate register char *p1, *p2; 497*7c478bd9Sstevel@tonic-gate register int i; 498*7c478bd9Sstevel@tonic-gate char *name1, *name2; 499*7c478bd9Sstevel@tonic-gate register time_t time1, time2; 500*7c478bd9Sstevel@tonic-gate register int seq1, seq2; 501*7c478bd9Sstevel@tonic-gate extern time_t num(); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate name1 = (*d1)->d_name; 504*7c478bd9Sstevel@tonic-gate name2 = (*d2)->d_name; 505*7c478bd9Sstevel@tonic-gate if ((p1 = strchr(name1, '.')) == NULL) 506*7c478bd9Sstevel@tonic-gate return (1); 507*7c478bd9Sstevel@tonic-gate if ((p2 = strchr(name2, '.')) == NULL) 508*7c478bd9Sstevel@tonic-gate return (1); 509*7c478bd9Sstevel@tonic-gate p1++; 510*7c478bd9Sstevel@tonic-gate p2++; 511*7c478bd9Sstevel@tonic-gate if ((i = *p1++ - *p2++) != 0) 512*7c478bd9Sstevel@tonic-gate return (i); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate time1 = num(&name1); 515*7c478bd9Sstevel@tonic-gate time2 = num(&name2); 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate if (time1 < time2) 518*7c478bd9Sstevel@tonic-gate return (-1); 519*7c478bd9Sstevel@tonic-gate else if (time1 > time2) 520*7c478bd9Sstevel@tonic-gate return (1); 521*7c478bd9Sstevel@tonic-gate p1++; 522*7c478bd9Sstevel@tonic-gate p2++; 523*7c478bd9Sstevel@tonic-gate seq1 = atoi(p1); 524*7c478bd9Sstevel@tonic-gate seq2 = atoi(p2); 525*7c478bd9Sstevel@tonic-gate return (seq1 - seq2); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* 530*7c478bd9Sstevel@tonic-gate * Print usage info and exit. 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate usage() 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate fprintf(stderr, "usage: atq [-c] [-n] [name ...]\n"); 535*7c478bd9Sstevel@tonic-gate exit(1); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate aterror(msg) 539*7c478bd9Sstevel@tonic-gate char *msg; 540*7c478bd9Sstevel@tonic-gate { 541*7c478bd9Sstevel@tonic-gate fprintf(stderr, "atq: %s\n", msg); 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate atperror(msg) 545*7c478bd9Sstevel@tonic-gate char *msg; 546*7c478bd9Sstevel@tonic-gate { 547*7c478bd9Sstevel@tonic-gate fprintf(stderr, "atq: %s: %s\n", msg, errmsg(errno)); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate atabort(msg) 551*7c478bd9Sstevel@tonic-gate char *msg; 552*7c478bd9Sstevel@tonic-gate { 553*7c478bd9Sstevel@tonic-gate aterror(msg); 554*7c478bd9Sstevel@tonic-gate exit(1); 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate atabortperror(msg) 558*7c478bd9Sstevel@tonic-gate char *msg; 559*7c478bd9Sstevel@tonic-gate { 560*7c478bd9Sstevel@tonic-gate atperror(msg); 561*7c478bd9Sstevel@tonic-gate exit(1); 562*7c478bd9Sstevel@tonic-gate } 563