|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)atrm.c 5.2 (Berkeley) 5/28/86"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * synopsis: atrm [-f] [-i] [-] [[job #] [user] ...] ! 19: * ! 20: * ! 21: * Remove files from the directory /usr/spool/at. These files ! 22: * represent jobs to be run at a later date. ! 23: * ! 24: * Author: Steve Wall ! 25: * Computer Systems Research Group ! 26: * University of California @ Berkeley ! 27: * ! 28: */ ! 29: ! 30: #include <stdio.h> ! 31: #include <pwd.h> ! 32: #include <ctype.h> ! 33: #include <sys/types.h> ! 34: #include <sys/dir.h> ! 35: #include <sys/file.h> ! 36: #include <sys/stat.h> ! 37: ! 38: #define SUPERUSER 0 /* is user super-user? */ ! 39: #define MAXENTRIES 1000 /* max # of entries allowed */ ! 40: #define ATDIR "/usr/spool/at" /* spooling area */ ! 41: ! 42: ! 43: int user; /* person requesting removal */ ! 44: int fflag = 0; /* suppress announcements? */ ! 45: int iflag = 0; /* run interactively? */ ! 46: ! 47: main(argc,argv) ! 48: int argc; ! 49: char **argv; ! 50: ! 51: { ! 52: int i; /* for loop index */ ! 53: int userid; /* uid of owner of file */ ! 54: int isuname; /* is a command line argv a user name?*/ ! 55: int numjobs; /* # of jobs in spooling area */ ! 56: int usage(); /* print usage info and exit */ ! 57: int allflag = 0; /* remove all jobs belonging to user? */ ! 58: int jobexists; /* does a requested job exist? */ ! 59: int alphasort(); /* sort jobs by date of execution */ ! 60: int filewanted(); /* should a file be listed in queue? */ ! 61: char *getname(); /* get a user name from a uid */ ! 62: struct stat *statptr; /* pointer to file stat structure */ ! 63: struct stat *stbuf[MAXENTRIES]; /* array of pointers to stat structs */ ! 64: struct direct **namelist; /* names of jobs in spooling area */ ! 65: ! 66: ! 67: /* ! 68: * If job number, user name, or "-" is not specified, just print ! 69: * usage info and exit. ! 70: */ ! 71: if (argc < 2) ! 72: usage(); ! 73: ! 74: --argc; ++argv; ! 75: ! 76: /* ! 77: * Process command line flags. ! 78: * Special case the "-" option so that others may be grouped. ! 79: */ ! 80: while (argc > 0 && **argv == '-') { ! 81: if (*(++(*argv)) == '\0') { ! 82: ++allflag; ! 83: } else while (**argv) switch (*(*argv)++) { ! 84: ! 85: case 'f': ++fflag; ! 86: break; ! 87: ! 88: case 'i': ++iflag; ! 89: break; ! 90: ! 91: default: usage(); ! 92: } ! 93: ++argv; --argc; ! 94: } ! 95: ! 96: /* ! 97: * If all jobs are to be removed and extra command line arguments ! 98: * are given, print usage info and exit. ! 99: */ ! 100: if (allflag && argc) ! 101: usage(); ! 102: ! 103: /* ! 104: * If only certain jobs are to be removed and no job #'s or user ! 105: * names are specified, print usage info and exit. ! 106: */ ! 107: if (!allflag && !argc) ! 108: usage(); ! 109: ! 110: /* ! 111: * If interactive removal and quiet removal are requested, override ! 112: * quiet removal and run interactively. ! 113: */ ! 114: if (iflag && fflag) ! 115: fflag = 0; ! 116: ! 117: /* ! 118: * Move to spooling area and get user id of person requesting removal. ! 119: */ ! 120: if (chdir(ATDIR) == -1) { ! 121: perror(ATDIR); ! 122: exit(1); ! 123: } ! 124: user = getuid(); ! 125: ! 126: /* ! 127: * Get a list of the files in the spooling area. ! 128: */ ! 129: if ((numjobs = scandir(".",&namelist,filewanted,alphasort)) < 0) { ! 130: perror(ATDIR); ! 131: exit(1); ! 132: } ! 133: ! 134: /* ! 135: * Build an array of pointers to the file stats for all jobs in ! 136: * the spooling area. ! 137: */ ! 138: for (i = 0; i < numjobs; ++i) { ! 139: statptr = (struct stat *) malloc(sizeof(struct stat)); ! 140: if (statptr == NULL) { ! 141: perror("malloc"); ! 142: exit(1); ! 143: } ! 144: if (stat(namelist[i]->d_name,statptr) < 0) { ! 145: perror("stat"); ! 146: continue; ! 147: } ! 148: stbuf[i] = statptr; ! 149: } ! 150: ! 151: /* ! 152: * If all jobs belonging to the user are to be removed, compare ! 153: * the user's id to the owner of the file. If they match, remove ! 154: * the file. If the user is the super-user, don't bother comparing ! 155: * the id's. After all files are removed, exit (status 0). ! 156: */ ! 157: if (allflag) { ! 158: for (i = 0; i < numjobs; ++i) { ! 159: if (user == SUPERUSER || isowner(getname(user), ! 160: namelist[i]->d_name)) ! 161: (void) removentry(namelist[i]->d_name, ! 162: (int)stbuf[i]->st_ino, ! 163: user); ! 164: } ! 165: exit(0); ! 166: } ! 167: ! 168: /* ! 169: * If only certain jobs are to be removed, interpret each command ! 170: * line argument. A check is done to see if it is a user's name or ! 171: * a job number (inode #). If it's a user's name, compare the argument ! 172: * to the files owner. If it's a job number, compare the argument to ! 173: * the inode number of the file. In either case, if a match occurs, ! 174: * try to remove the file. (The function "isusername" scans the ! 175: * argument to see if it is all digits which we will assume means ! 176: * that it's a job number (a fairly safe assumption?). This is done ! 177: * because we have to determine whether we are dealing with a user ! 178: * name or a job number. By assuming that only arguments that are ! 179: * all digits is a job number, we allow users to have digits in ! 180: * their login name i.e. "johndoe2"). ! 181: */ ! 182: ! 183: while (argc--) { ! 184: jobexists = 0; ! 185: isuname = isusername(*argv); ! 186: for (i = 0; i < numjobs; ++i) { ! 187: ! 188: /* if the inode number is 0, this entry was removed */ ! 189: if (stbuf[i]->st_ino == 0) ! 190: continue; ! 191: ! 192: /* ! 193: * if argv is a username, compare his/her uid to ! 194: * the uid of the owner of the file...... ! 195: */ ! 196: if (isuname) { ! 197: if (!isowner(*argv,namelist[i]->d_name)) ! 198: continue; ! 199: ! 200: /* ! 201: * otherwise, we assume that the argv is a job # and ! 202: * thus compare argv to the inode (job #) of the file. ! 203: */ ! 204: } else { ! 205: if (stbuf[i]->st_ino != atoi(*argv)) ! 206: continue; ! 207: } ! 208: ++jobexists; ! 209: /* ! 210: * if the entry is ultimately removed, don't ! 211: * try to remove it again later. ! 212: */ ! 213: if (removentry(namelist[i]->d_name, ! 214: (int)stbuf[i]->st_ino, user)) { ! 215: stbuf[i]->st_ino = 0; ! 216: } ! 217: } ! 218: ! 219: /* ! 220: * If a requested argument doesn't exist, print a message. ! 221: */ ! 222: if (!jobexists && !fflag && !isuname) { ! 223: fprintf(stderr, "%6s: no such job number\n", *argv); ! 224: } ! 225: ++argv; ! 226: } ! 227: exit(0); ! 228: } ! 229: ! 230: /* ! 231: * Print usage info and exit. ! 232: */ ! 233: usage() ! 234: { ! 235: fprintf(stderr,"usage: atrm [-f] [-i] [-] [[job #] [user] ...]\n"); ! 236: exit(1); ! 237: } ! 238: ! 239: /* ! 240: * Do we want to include a file in the queue? (used by "scandir") We are looking ! 241: * for files with following syntax: yy.ddd.hhhh. so the test is made to see if ! 242: * the file name has three dots in it. This test will suffice since the only ! 243: * other files in /usr/spool/at don't have any dots in their name. ! 244: */ ! 245: filewanted(direntry) ! 246: struct direct *direntry; ! 247: { ! 248: int numdot = 0; /* number of dots in a filename */ ! 249: char *filename; /* filename we are looking at */ ! 250: ! 251: filename = direntry->d_name; ! 252: while (*filename) ! 253: numdot += (*(filename++) == '.'); ! 254: return(numdot == 3); ! 255: } ! 256: ! 257: /* ! 258: * Is a command line argument a username? As noted above we will assume ! 259: * that an argument that is all digits means that it's a job number, not ! 260: * a user's name. We choose to determine whether an argument is a user name ! 261: * in this manner because then it's ok for someone to have digits in their ! 262: * user name. ! 263: */ ! 264: isusername(string) ! 265: char *string; ! 266: { ! 267: char *ptr; /* pointer used for scanning string */ ! 268: ! 269: ptr = string; ! 270: while (isdigit(*ptr)) ! 271: ++ptr; ! 272: return((*ptr == '\0') ? 0 : 1); ! 273: } ! 274: ! 275: /* ! 276: * Remove an entry from the queue. The access of the file is checked for ! 277: * write permission (since all jobs are mode 644). If access is granted, ! 278: * unlink the file. If the fflag (suppress announcements) is not set, ! 279: * print the job number that we are removing and the result of the access ! 280: * check (either "permission denied" or "removed"). If we are running ! 281: * interactively (iflag), prompt the user before we unlink the file. If ! 282: * the super-user is removing jobs, inform him/her who owns each file before ! 283: * it is removed. Return TRUE if file removed, else FALSE. ! 284: */ ! 285: int ! 286: removentry(filename,inode,user) ! 287: char *filename; ! 288: int inode; ! 289: int user; ! 290: { ! 291: ! 292: if (!fflag) ! 293: printf("%6d: ",inode); ! 294: ! 295: if (!isowner(getname(user),filename) && user != SUPERUSER) { ! 296: ! 297: if (!fflag) { ! 298: printf("permission denied\n"); ! 299: } ! 300: return (0); ! 301: ! 302: } else { ! 303: if (iflag) { ! 304: if (user == SUPERUSER) { ! 305: printf("\t(owned by "); ! 306: powner(filename); ! 307: printf(") "); ! 308: } ! 309: printf("remove it? "); ! 310: if (!yes()) ! 311: return (0); ! 312: } ! 313: if (unlink(filename) < 0) { ! 314: if (!fflag) { ! 315: fputs("could not remove\n", stdout); ! 316: perror(filename); ! 317: } ! 318: return (0); ! 319: } ! 320: if (!fflag && !iflag) ! 321: printf("removed\n"); ! 322: return (1); ! 323: } ! 324: } ! 325: ! 326: /* ! 327: * See if "name" owns "job". ! 328: */ ! 329: isowner(name,job) ! 330: char *name; ! 331: char *job; ! 332: { ! 333: char buf[128]; /* buffer for 1st line of spoolfile ! 334: header */ ! 335: FILE *infile; /* I/O stream to spoolfile */ ! 336: ! 337: if ((infile = fopen(job,"r")) == NULL) { ! 338: fprintf(stderr,"Couldn't open spoolfile "); ! 339: perror(job); ! 340: return(0); ! 341: } ! 342: ! 343: if (fscanf(infile,"# owner: %127s%*[^\n]\n",buf) != 1) { ! 344: fclose(infile); ! 345: return(0); ! 346: } ! 347: ! 348: fclose(infile); ! 349: return((strcmp(name,buf) == 0) ? 1 : 0); ! 350: } ! 351: ! 352: /* ! 353: * Print the owner of the job. This is stored on the first line of the ! 354: * spoolfile. If we run into trouble getting the name, we'll just print "???". ! 355: */ ! 356: powner(file) ! 357: char *file; ! 358: { ! 359: char owner[128]; /* the owner */ ! 360: FILE *infile; /* I/O stream to spoolfile */ ! 361: ! 362: /* ! 363: * Open the job file and grab the first line. ! 364: */ ! 365: ! 366: if ((infile = fopen(file,"r")) == NULL) { ! 367: printf("%s","???"); ! 368: perror(file); ! 369: return; ! 370: } ! 371: ! 372: if (fscanf(infile,"# owner: %127s%*[^\n]\n",owner) != 1) { ! 373: printf("%s","???"); ! 374: fclose(infile); ! 375: return; ! 376: } ! 377: ! 378: fclose(infile); ! 379: printf("%s",owner); ! 380: ! 381: } ! 382: ! 383: /* ! 384: * Get answer to interactive prompts, eating all characters beyond the first ! 385: * one. If a 'y' is typed, return 1. ! 386: */ ! 387: yes() ! 388: { ! 389: char ch; /* dummy variable */ ! 390: char ch1; /* dummy variable */ ! 391: ! 392: ch = ch1 = getchar(); ! 393: while (ch1 != '\n' && ch1 != EOF) ! 394: ch1 = getchar(); ! 395: if (isupper(ch)) ! 396: ch = tolower(ch); ! 397: return(ch == 'y'); ! 398: } ! 399: ! 400: /* ! 401: * Get the uid of a person using his/her login name. Return -1 if no ! 402: * such account name exists. ! 403: */ ! 404: getid(name) ! 405: char *name; ! 406: { ! 407: ! 408: struct passwd *pwdinfo; /* password info structure */ ! 409: ! 410: if ((pwdinfo = getpwnam(name)) == 0) ! 411: return(-1); ! 412: ! 413: return(pwdinfo->pw_uid); ! 414: } ! 415: ! 416: /* ! 417: * Get the full login name of a person using his/her user id. ! 418: */ ! 419: char * ! 420: getname(uid) ! 421: int uid; ! 422: { ! 423: struct passwd *pwdinfo; /* password info structure */ ! 424: ! 425: ! 426: if ((pwdinfo = getpwuid(uid)) == 0) ! 427: return("???"); ! 428: return(pwdinfo->pw_name); ! 429: } ! 430:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.