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