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 * Copyright 1984-2002 Sun Microsystems, Inc. All rights reserved. 11*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 12*7c478bd9Sstevel@tonic-gate */ 13*7c478bd9Sstevel@tonic-gate 14*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.5 */ 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate /* 17*7c478bd9Sstevel@tonic-gate * synopsis: atrm [-f] [-i] [-a] [[job #] [user] ...] 18*7c478bd9Sstevel@tonic-gate * 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * Remove "at" jobs. 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate 23*7c478bd9Sstevel@tonic-gate #include <stdio.h> 24*7c478bd9Sstevel@tonic-gate #include <pwd.h> 25*7c478bd9Sstevel@tonic-gate #include <ctype.h> 26*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 27*7c478bd9Sstevel@tonic-gate #include <dirent.h> 28*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 29*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 30*7c478bd9Sstevel@tonic-gate #include <errno.h> 31*7c478bd9Sstevel@tonic-gate #include <unistd.h> 32*7c478bd9Sstevel@tonic-gate #include <locale.h> 33*7c478bd9Sstevel@tonic-gate #include "cron.h" 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate extern time_t num(); 36*7c478bd9Sstevel@tonic-gate extern char *errmsg(); 37*7c478bd9Sstevel@tonic-gate extern int errno; 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate extern void audit_at_delete(char *, char *, int); 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #define SUPERUSER 0 /* is user super-user? */ 42*7c478bd9Sstevel@tonic-gate #define CANTCD "can't change directory to the at directory" 43*7c478bd9Sstevel@tonic-gate #define NOREADDIR "can't read the at directory" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate uid_t user; /* person requesting removal */ 46*7c478bd9Sstevel@tonic-gate int fflag = 0; /* suppress announcements? */ 47*7c478bd9Sstevel@tonic-gate int iflag = 0; /* run interactively? */ 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate char login[UNAMESIZE]; 50*7c478bd9Sstevel@tonic-gate char login_authchk[UNAMESIZE]; /* used for authorization checks */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)" 53*7c478bd9Sstevel@tonic-gate #define NOTALLOWED "you are not authorized to use at. Sorry." 54*7c478bd9Sstevel@tonic-gate #define NAMETOOLONG "login name too long" 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate main(argc,argv) 57*7c478bd9Sstevel@tonic-gate int argc; 58*7c478bd9Sstevel@tonic-gate char **argv; 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate { 61*7c478bd9Sstevel@tonic-gate int i; /* for loop index */ 62*7c478bd9Sstevel@tonic-gate int numjobs; /* # of jobs in spooling area */ 63*7c478bd9Sstevel@tonic-gate int usage(); /* print usage info and exit */ 64*7c478bd9Sstevel@tonic-gate int allflag = 0; /* remove all jobs belonging to user? */ 65*7c478bd9Sstevel@tonic-gate int jobexists; /* does a requested job exist? */ 66*7c478bd9Sstevel@tonic-gate extern int strcmp(); /* sort jobs by date of execution */ 67*7c478bd9Sstevel@tonic-gate char *pp; 68*7c478bd9Sstevel@tonic-gate char *getuser(); 69*7c478bd9Sstevel@tonic-gate struct dirent **namelist; /* names of jobs in spooling area */ 70*7c478bd9Sstevel@tonic-gate struct stat **statlist; 71*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * If job number, user name, or "-" is not specified, just print 75*7c478bd9Sstevel@tonic-gate * usage info and exit. 76*7c478bd9Sstevel@tonic-gate */ 77*7c478bd9Sstevel@tonic-gate (void)setlocale(LC_ALL, ""); 78*7c478bd9Sstevel@tonic-gate if (argc < 2) 79*7c478bd9Sstevel@tonic-gate usage(); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate --argc; ++argv; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate pp = getuser((user=getuid())); 84*7c478bd9Sstevel@tonic-gate if (pp == NULL) 85*7c478bd9Sstevel@tonic-gate atabort(INVALIDUSER); 86*7c478bd9Sstevel@tonic-gate if (strlcpy(login, pp, sizeof (login)) >= sizeof (login)) 87*7c478bd9Sstevel@tonic-gate atabort(NAMETOOLONG); 88*7c478bd9Sstevel@tonic-gate if (strlcpy(login_authchk, pp, sizeof (login_authchk)) 89*7c478bd9Sstevel@tonic-gate >= sizeof (NAMETOOLONG)) 90*7c478bd9Sstevel@tonic-gate atabort(INVALIDUSER); 91*7c478bd9Sstevel@tonic-gate if (!allowed(login, ATALLOW, ATDENY)) 92*7c478bd9Sstevel@tonic-gate atabort(NOTALLOWED); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * Process command line flags. 96*7c478bd9Sstevel@tonic-gate * Special case the "-" option so that others may be grouped. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate while (argc > 0 && **argv == '-') { 99*7c478bd9Sstevel@tonic-gate *(*argv)++; 100*7c478bd9Sstevel@tonic-gate while (**argv) switch (*(*argv)++) { 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate case 'a': ++allflag; 103*7c478bd9Sstevel@tonic-gate break; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate case 'f': ++fflag; 106*7c478bd9Sstevel@tonic-gate break; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate case 'i': ++iflag; 109*7c478bd9Sstevel@tonic-gate break; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate default: usage(); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate ++argv; --argc; 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* 117*7c478bd9Sstevel@tonic-gate * If all jobs are to be removed and extra command line arguments 118*7c478bd9Sstevel@tonic-gate * are given, print usage info and exit. 119*7c478bd9Sstevel@tonic-gate */ 120*7c478bd9Sstevel@tonic-gate if (allflag && argc) 121*7c478bd9Sstevel@tonic-gate usage(); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * If only certain jobs are to be removed and no job #'s or user 125*7c478bd9Sstevel@tonic-gate * names are specified, print usage info and exit. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate if (!allflag && !argc) 128*7c478bd9Sstevel@tonic-gate usage(); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * If interactive removal and quiet removal are requested, override 132*7c478bd9Sstevel@tonic-gate * quiet removal and run interactively. 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate if (iflag && fflag) 135*7c478bd9Sstevel@tonic-gate fflag = 0; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* 139*7c478bd9Sstevel@tonic-gate * Move to spooling directory and get a list of the files in the 140*7c478bd9Sstevel@tonic-gate * spooling area. 141*7c478bd9Sstevel@tonic-gate */ 142*7c478bd9Sstevel@tonic-gate numjobs = getjoblist(&namelist,&statlist,strcmp); 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * If all jobs belonging to the user are to be removed, compare 145*7c478bd9Sstevel@tonic-gate * the user's id to the owner of the file. If they match, remove 146*7c478bd9Sstevel@tonic-gate * the file. If the user is the super-user, don't bother comparing 147*7c478bd9Sstevel@tonic-gate * the id's. After all files are removed, exit (status 0). 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate if (allflag) { 150*7c478bd9Sstevel@tonic-gate for (i = 0; i < numjobs; ++i) { 151*7c478bd9Sstevel@tonic-gate if (chkauthattr(CRONADMIN_AUTH, login_authchk) || 152*7c478bd9Sstevel@tonic-gate user == statlist[i]->st_uid) 153*7c478bd9Sstevel@tonic-gate (void) removentry(namelist[i]->d_name, 154*7c478bd9Sstevel@tonic-gate statlist[i], user); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate exit(0); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate /* 160*7c478bd9Sstevel@tonic-gate * If only certain jobs are to be removed, interpret each command 161*7c478bd9Sstevel@tonic-gate * line argument. A check is done to see if it is a user's name or 162*7c478bd9Sstevel@tonic-gate * a job number (inode #). If it's a user's name, compare the argument 163*7c478bd9Sstevel@tonic-gate * to the files owner. If it's a job number, compare the argument to 164*7c478bd9Sstevel@tonic-gate * the file name. In either case, if a match occurs, try to 165*7c478bd9Sstevel@tonic-gate * remove the file. 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate while (argc--) { 169*7c478bd9Sstevel@tonic-gate jobexists = 0; 170*7c478bd9Sstevel@tonic-gate for (i = 0; i < numjobs; ++i) { 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* if the inode number is 0, this entry was removed */ 173*7c478bd9Sstevel@tonic-gate if (statlist[i]->st_ino == 0) 174*7c478bd9Sstevel@tonic-gate continue; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * if argv is a username, compare his/her uid to 178*7c478bd9Sstevel@tonic-gate * the uid of the owner of the file...... 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate if (pwd = getpwnam(*argv)) { 181*7c478bd9Sstevel@tonic-gate if (statlist[i]->st_uid != pwd->pw_uid) 182*7c478bd9Sstevel@tonic-gate continue; 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * otherwise, we assume that the argv is a job # and 185*7c478bd9Sstevel@tonic-gate * thus compare argv to the file name. 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate } else { 188*7c478bd9Sstevel@tonic-gate if (strcmp(namelist[i]->d_name,*argv)) 189*7c478bd9Sstevel@tonic-gate continue; 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate ++jobexists; 192*7c478bd9Sstevel@tonic-gate /* 193*7c478bd9Sstevel@tonic-gate * if the entry is ultimately removed, don't 194*7c478bd9Sstevel@tonic-gate * try to remove it again later. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate if (removentry(namelist[i]->d_name, statlist[i], user)) { 197*7c478bd9Sstevel@tonic-gate statlist[i]->st_ino = 0; 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * If a requested argument doesn't exist, print a message. 203*7c478bd9Sstevel@tonic-gate */ 204*7c478bd9Sstevel@tonic-gate if (!jobexists && !fflag) { 205*7c478bd9Sstevel@tonic-gate fprintf(stderr, "atrm: %s: no such job number\n", *argv); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate ++argv; 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate exit(0); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * Print usage info and exit. 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate usage() 216*7c478bd9Sstevel@tonic-gate { 217*7c478bd9Sstevel@tonic-gate fprintf(stderr,"usage: atrm [-f] [-i] [-a] [[job #] [user] ...]\n"); 218*7c478bd9Sstevel@tonic-gate exit(1); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * Remove an entry from the queue. The access of the file is checked for 224*7c478bd9Sstevel@tonic-gate * write permission (since all jobs are mode 644). If access is granted, 225*7c478bd9Sstevel@tonic-gate * unlink the file. If the fflag (suppress announcements) is not set, 226*7c478bd9Sstevel@tonic-gate * print the job number that we are removing and the result of the access 227*7c478bd9Sstevel@tonic-gate * check (either "permission denied" or "removed"). If we are running 228*7c478bd9Sstevel@tonic-gate * interactively (iflag), prompt the user before we unlink the file. If 229*7c478bd9Sstevel@tonic-gate * the super-user is removing jobs, inform him/her who owns each file before 230*7c478bd9Sstevel@tonic-gate * it is removed. Return TRUE if file removed, else FALSE. 231*7c478bd9Sstevel@tonic-gate */ 232*7c478bd9Sstevel@tonic-gate int 233*7c478bd9Sstevel@tonic-gate removentry(filename,statptr,user) 234*7c478bd9Sstevel@tonic-gate char *filename; 235*7c478bd9Sstevel@tonic-gate register struct stat *statptr; 236*7c478bd9Sstevel@tonic-gate uid_t user; 237*7c478bd9Sstevel@tonic-gate { 238*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 239*7c478bd9Sstevel@tonic-gate char *pp; 240*7c478bd9Sstevel@tonic-gate char *getuser(); 241*7c478bd9Sstevel@tonic-gate int r; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate if (!fflag) 244*7c478bd9Sstevel@tonic-gate printf("%s: ",filename); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate if (user != statptr->st_uid && 247*7c478bd9Sstevel@tonic-gate !chkauthattr(CRONADMIN_AUTH, login_authchk)) { 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if (!fflag) { 250*7c478bd9Sstevel@tonic-gate printf("permission denied\n"); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate return (0); 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate } else { 255*7c478bd9Sstevel@tonic-gate if (iflag) { 256*7c478bd9Sstevel@tonic-gate if (chkauthattr(CRONADMIN_AUTH, login_authchk)) { 257*7c478bd9Sstevel@tonic-gate printf("\t(owned by "); 258*7c478bd9Sstevel@tonic-gate powner(filename); 259*7c478bd9Sstevel@tonic-gate printf(") "); 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate printf("remove it? "); 262*7c478bd9Sstevel@tonic-gate if (!yes()) 263*7c478bd9Sstevel@tonic-gate return (0); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if (chkauthattr(CRONADMIN_AUTH, login_authchk)) { 267*7c478bd9Sstevel@tonic-gate pp = getuser((uid_t) statptr->st_uid); 268*7c478bd9Sstevel@tonic-gate if (pp == NULL) 269*7c478bd9Sstevel@tonic-gate atabort(INVALIDUSER); 270*7c478bd9Sstevel@tonic-gate if (strlcpy(login, pp, sizeof (login)) >= 271*7c478bd9Sstevel@tonic-gate sizeof (login)) 272*7c478bd9Sstevel@tonic-gate atabort(NAMETOOLONG); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate cron_sendmsg(DELETE,login,filename,AT); 275*7c478bd9Sstevel@tonic-gate if ((r = unlink(filename)) < 0) { 276*7c478bd9Sstevel@tonic-gate if (!fflag) { 277*7c478bd9Sstevel@tonic-gate fputs("could not remove\n", stdout); 278*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "atrm: %s: %s\n", 279*7c478bd9Sstevel@tonic-gate filename, errmsg(errno)); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate audit_at_delete(filename, NULL, r); 282*7c478bd9Sstevel@tonic-gate return (0); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate audit_at_delete(filename, NULL, r); 285*7c478bd9Sstevel@tonic-gate if (!fflag && !iflag) 286*7c478bd9Sstevel@tonic-gate printf("removed\n"); 287*7c478bd9Sstevel@tonic-gate return (1); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /* 292*7c478bd9Sstevel@tonic-gate * Print the owner of the job. This is the owner of the spoolfile. 293*7c478bd9Sstevel@tonic-gate * If we run into trouble getting the name, we'll just print "???". 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate powner(file) 296*7c478bd9Sstevel@tonic-gate char *file; 297*7c478bd9Sstevel@tonic-gate { 298*7c478bd9Sstevel@tonic-gate struct stat statb; 299*7c478bd9Sstevel@tonic-gate char *getname(); 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if (stat(file,&statb) < 0) { 302*7c478bd9Sstevel@tonic-gate printf("%s","???"); 303*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,"atrm: Couldn't stat spoolfile %s: %s\n", 304*7c478bd9Sstevel@tonic-gate file, errmsg(errno)); 305*7c478bd9Sstevel@tonic-gate return(0); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate printf("%s",getname(statb.st_uid)); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate int 313*7c478bd9Sstevel@tonic-gate getjoblist(namelistp, statlistp,sortfunc) 314*7c478bd9Sstevel@tonic-gate struct dirent ***namelistp; 315*7c478bd9Sstevel@tonic-gate struct stat ***statlistp; 316*7c478bd9Sstevel@tonic-gate int (*sortfunc)(); 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate register int numjobs; 319*7c478bd9Sstevel@tonic-gate register struct dirent **namelist; 320*7c478bd9Sstevel@tonic-gate register int i; 321*7c478bd9Sstevel@tonic-gate register struct stat *statptr; /* pointer to file stat structure */ 322*7c478bd9Sstevel@tonic-gate register struct stat **statlist; 323*7c478bd9Sstevel@tonic-gate extern int alphasort(); /* sort jobs by date of execution */ 324*7c478bd9Sstevel@tonic-gate extern int filewanted(); /* should a file be listed in queue? */ 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate if (chdir(ATDIR) < 0) 327*7c478bd9Sstevel@tonic-gate atabortperror(CANTCD); 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate /* 330*7c478bd9Sstevel@tonic-gate * Get a list of the files in the spooling area. 331*7c478bd9Sstevel@tonic-gate */ 332*7c478bd9Sstevel@tonic-gate if ((numjobs = ascandir(".",namelistp,filewanted,sortfunc)) < 0) 333*7c478bd9Sstevel@tonic-gate atabortperror(NOREADDIR); 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate if ((statlist = (struct stat **) malloc(numjobs * sizeof (struct stat ***))) == NULL) 336*7c478bd9Sstevel@tonic-gate atabort("Out of memory"); 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate namelist = *namelistp; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* 341*7c478bd9Sstevel@tonic-gate * Build an array of pointers to the file stats for all jobs in 342*7c478bd9Sstevel@tonic-gate * the spooling area. 343*7c478bd9Sstevel@tonic-gate */ 344*7c478bd9Sstevel@tonic-gate for (i = 0; i < numjobs; ++i) { 345*7c478bd9Sstevel@tonic-gate statptr = (struct stat *) malloc(sizeof(struct stat)); 346*7c478bd9Sstevel@tonic-gate if (statptr == NULL) 347*7c478bd9Sstevel@tonic-gate atabort("Out of memory"); 348*7c478bd9Sstevel@tonic-gate if (stat(namelist[i]->d_name, statptr) < 0) { 349*7c478bd9Sstevel@tonic-gate atperror("Can't stat", namelist[i]->d_name); 350*7c478bd9Sstevel@tonic-gate continue; 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate statlist[i] = statptr; 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate *statlistp = statlist; 356*7c478bd9Sstevel@tonic-gate return (numjobs); 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * Get answer to interactive prompts, eating all characters beyond the first 362*7c478bd9Sstevel@tonic-gate * one. If a 'y' is typed, return 1. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate yes() 365*7c478bd9Sstevel@tonic-gate { 366*7c478bd9Sstevel@tonic-gate register int ch; /* dummy variable */ 367*7c478bd9Sstevel@tonic-gate register int ch1; /* dummy variable */ 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate ch = ch1 = getchar(); 370*7c478bd9Sstevel@tonic-gate while (ch1 != '\n' && ch1 != EOF) 371*7c478bd9Sstevel@tonic-gate ch1 = getchar(); 372*7c478bd9Sstevel@tonic-gate if (isupper(ch)) 373*7c478bd9Sstevel@tonic-gate ch = tolower(ch); 374*7c478bd9Sstevel@tonic-gate return(ch == 'y'); 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * Get the full login name of a person using his/her user id. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate char * 382*7c478bd9Sstevel@tonic-gate getname(uid) 383*7c478bd9Sstevel@tonic-gate uid_t uid; 384*7c478bd9Sstevel@tonic-gate { 385*7c478bd9Sstevel@tonic-gate register struct passwd *pwdinfo; /* password info structure */ 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate if ((pwdinfo = getpwuid(uid)) == 0) 389*7c478bd9Sstevel@tonic-gate return("???"); 390*7c478bd9Sstevel@tonic-gate return(pwdinfo->pw_name); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate aterror(msg) 394*7c478bd9Sstevel@tonic-gate char *msg; 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate fprintf(stderr,"atrm: %s\n",msg); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate atperror(msg) 400*7c478bd9Sstevel@tonic-gate char *msg; 401*7c478bd9Sstevel@tonic-gate { 402*7c478bd9Sstevel@tonic-gate fprintf(stderr,"atrm: %s: %s\n", msg, errmsg(errno)); 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate atabort(msg) 406*7c478bd9Sstevel@tonic-gate char *msg; 407*7c478bd9Sstevel@tonic-gate { 408*7c478bd9Sstevel@tonic-gate aterror(msg); 409*7c478bd9Sstevel@tonic-gate exit(1); 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate atabortperror(msg) 413*7c478bd9Sstevel@tonic-gate char *msg; 414*7c478bd9Sstevel@tonic-gate { 415*7c478bd9Sstevel@tonic-gate atperror(msg); 416*7c478bd9Sstevel@tonic-gate exit(1); 417*7c478bd9Sstevel@tonic-gate } 418