|
|
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.5 (Berkeley) 5/11/89"; ! 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 <sys/types.h> ! 31: #include <sys/dir.h> ! 32: #include <sys/file.h> ! 33: #include <sys/stat.h> ! 34: #include <stdio.h> ! 35: #include <pwd.h> ! 36: #include <ctype.h> ! 37: #include "pathnames.h" ! 38: ! 39: #define SUPERUSER 0 /* is user super-user? */ ! 40: #define MAXENTRIES 1000 /* max # of entries allowed */ ! 41: ! 42: int user; /* person requesting removal */ ! 43: int fflag = 0; /* suppress announcements? */ ! 44: int iflag = 0; /* run interactively? */ ! 45: ! 46: main(argc,argv) ! 47: int argc; ! 48: char **argv; ! 49: ! 50: { ! 51: register int i; /* for loop index */ ! 52: int isuname; /* is a command line argv a user name?*/ ! 53: int numjobs; /* # of jobs in spooling area */ ! 54: int usage(); /* print usage info and exit */ ! 55: int allflag = 0; /* remove all jobs belonging to user? */ ! 56: int jobno; ! 57: int jobexists; /* does a requested job exist? */ ! 58: int alphasort(); /* sort jobs by date of execution */ ! 59: int filewanted(); /* should a file be listed in queue? */ ! 60: char *myname, *getname(); /* current user's name */ ! 61: char *owner, *fowner(); ! 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(_PATH_ATDIR) == -1) { ! 121: perror(_PATH_ATDIR); ! 122: exit(1); ! 123: } ! 124: user = getuid(); ! 125: myname = getname(user); ! 126: ! 127: /* ! 128: * Get a list of the files in the spooling area. ! 129: */ ! 130: if ((numjobs = scandir(".",&namelist,filewanted,alphasort)) < 0) { ! 131: perror(_PATH_ATDIR); ! 132: exit(1); ! 133: } ! 134: ! 135: /* ! 136: * Build an array of pointers to the file stats for all jobs in ! 137: * the spooling area. ! 138: */ ! 139: for (i = 0; i < numjobs; ++i) { ! 140: statptr = (struct stat *) malloc(sizeof(struct stat)); ! 141: if (statptr == NULL) { ! 142: perror("malloc"); ! 143: exit(1); ! 144: } ! 145: if (stat(namelist[i]->d_name,statptr) < 0) { ! 146: perror("stat"); ! 147: continue; ! 148: } ! 149: stbuf[i] = statptr; ! 150: } ! 151: ! 152: /* ! 153: * If all jobs belonging to the user are to be removed, compare ! 154: * the user's id to the owner of the file. If they match, remove ! 155: * the file. If the user is the super-user, don't bother comparing ! 156: * the id's. After all files are removed, exit (status 0). ! 157: */ ! 158: if (allflag) { ! 159: for (i = 0; i < numjobs; ++i) { ! 160: owner = fowner(namelist[i]->d_name); ! 161: if (isowner(myname, owner)) ! 162: removentry(namelist[i]->d_name, ! 163: (int)stbuf[i]->st_ino, NULL); ! 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: if (!isuname) ! 187: jobno = atoi(*argv); ! 188: for (i = 0; i < numjobs; ++i) { ! 189: ! 190: /* if the inode number is 0, this entry was removed */ ! 191: if (stbuf[i]->st_ino == 0) ! 192: continue; ! 193: ! 194: owner = fowner(namelist[i]->d_name); ! 195: /* ! 196: * if argv is a username, compare it to ! 197: * the owner of the file...... ! 198: * otherwise, we assume that the argv is a job # and ! 199: * thus compare argv to the inode (job #) of the file. ! 200: */ ! 201: if (isuname) { ! 202: if (strcmp(*argv, owner)) ! 203: continue; ! 204: } else { ! 205: if (stbuf[i]->st_ino != jobno) ! 206: continue; ! 207: } ! 208: ++jobexists; ! 209: /* ! 210: * if the entry is removed, don't ! 211: * try to remove it again later. ! 212: */ ! 213: if (user == SUPERUSER || isowner(myname, owner)) { ! 214: removentry(namelist[i]->d_name, ! 215: (int)stbuf[i]->st_ino, owner); ! 216: stbuf[i]->st_ino = 0; ! 217: } else if (!fflag) ! 218: printf("%6d: permission denied\n", ! 219: stbuf[i]->st_ino); ! 220: if (!isuname) ! 221: break; ! 222: } ! 223: ! 224: /* ! 225: * If a requested argument doesn't exist, print a message. ! 226: */ ! 227: if (!jobexists && !fflag && !isuname) { ! 228: fprintf(stderr, "%6s: no such job number\n", *argv); ! 229: } ! 230: ++argv; ! 231: } ! 232: exit(0); ! 233: } ! 234: ! 235: /* ! 236: * Print usage info and exit. ! 237: */ ! 238: usage() ! 239: { ! 240: fprintf(stderr,"usage: atrm [-f] [-i] [-] [[job #] [user] ...]\n"); ! 241: exit(1); ! 242: } ! 243: ! 244: /* ! 245: * Do we want to include a file in the queue? (used by "scandir") We are looking ! 246: * for files with following syntax: yy.ddd.hhhh. so the test is made to see if ! 247: * the file name has three dots in it. This test will suffice since the only ! 248: * other files in /usr/spool/at don't have any dots in their name. ! 249: */ ! 250: filewanted(direntry) ! 251: struct direct *direntry; ! 252: { ! 253: int numdot = 0; /* number of dots in a filename */ ! 254: char *filename; /* filename we are looking at */ ! 255: ! 256: filename = direntry->d_name; ! 257: while (*filename) ! 258: numdot += (*(filename++) == '.'); ! 259: return(numdot == 3); ! 260: } ! 261: ! 262: /* ! 263: * Is a command line argument a username? As noted above we will assume ! 264: * that an argument that is all digits means that it's a job number, not ! 265: * a user's name. We choose to determine whether an argument is a user name ! 266: * in this manner because then it's ok for someone to have digits in their ! 267: * user name. ! 268: */ ! 269: isusername(string) ! 270: char *string; ! 271: { ! 272: char *ptr; /* pointer used for scanning string */ ! 273: ! 274: ptr = string; ! 275: while (isdigit(*ptr)) ! 276: ++ptr; ! 277: return((*ptr == '\0') ? 0 : 1); ! 278: } ! 279: ! 280: /* ! 281: * Remove an entry from the queue. The access of the file is checked for ! 282: * write permission (since all jobs are mode 644). If access is granted, ! 283: * unlink the file. If the fflag (suppress announcements) is not set, ! 284: * print the job number that we are removing and the result of the access ! 285: * check (either "permission denied" or "removed"). If we are running ! 286: * interactively (iflag), prompt the user before we unlink the file. If ! 287: * the super-user is removing jobs, inform him/her who owns each file before ! 288: * it is removed. ! 289: */ ! 290: removentry(filename, inode, owner) ! 291: char *filename; ! 292: int inode; ! 293: char *owner; ! 294: { ! 295: ! 296: if (!fflag) ! 297: printf("%6d: ",inode); ! 298: ! 299: if (iflag) { ! 300: if (user == SUPERUSER && owner) ! 301: printf("\t(owned by %s) ", owner); ! 302: printf("remove? "); ! 303: if (!yes()) ! 304: return; ! 305: } ! 306: if (unlink(filename) < 0) ! 307: perror(filename); ! 308: else if (!fflag && !iflag) ! 309: printf("removed\n"); ! 310: } ! 311: ! 312: /* ! 313: * See if "name" owns job owned by "jobname". ! 314: */ ! 315: isowner(name,jobname) ! 316: char *name; ! 317: char *jobname; ! 318: { ! 319: ! 320: return (strcmp(name,jobname) == 0); ! 321: } ! 322: ! 323: /* ! 324: * Return the owner of the job. This is stored on the first line of the ! 325: * spoolfile. If we run into trouble getting the name, we'll just return "???". ! 326: */ ! 327: char * ! 328: fowner(file) ! 329: char *file; ! 330: { ! 331: static char owner[128]; /* the owner */ ! 332: FILE *infile; /* I/O stream to spoolfile */ ! 333: ! 334: /* ! 335: * Open the job file and grab the first line. ! 336: */ ! 337: ! 338: if ((infile = fopen(file,"r")) == NULL) { ! 339: perror(file); ! 340: return ("???"); ! 341: } ! 342: ! 343: if (fscanf(infile,"# owner: %127s%*[^\n]\n",owner) != 1) { ! 344: fclose(infile); ! 345: return ("???"); ! 346: } ! 347: ! 348: fclose(infile); ! 349: return (owner); ! 350: ! 351: } ! 352: ! 353: /* ! 354: * Get answer to interactive prompts, eating all characters beyond the first ! 355: * one. If a 'y' is typed, return 1. ! 356: */ ! 357: yes() ! 358: { ! 359: char ch; /* dummy variable */ ! 360: char ch1; /* dummy variable */ ! 361: ! 362: ch = ch1 = getchar(); ! 363: while (ch1 != '\n' && ch1 != EOF) ! 364: ch1 = getchar(); ! 365: if (isupper(ch)) ! 366: ch = tolower(ch); ! 367: return(ch == 'y'); ! 368: } ! 369: ! 370: /* ! 371: * Get the uid of a person using his/her login name. Return -1 if no ! 372: * such account name exists. ! 373: */ ! 374: getid(name) ! 375: char *name; ! 376: { ! 377: ! 378: struct passwd *pwdinfo; /* password info structure */ ! 379: ! 380: if ((pwdinfo = getpwnam(name)) == 0) ! 381: return(-1); ! 382: ! 383: return(pwdinfo->pw_uid); ! 384: } ! 385: ! 386: /* ! 387: * Get the full login name of a person using his/her user id. ! 388: */ ! 389: char * ! 390: getname(uid) ! 391: int uid; ! 392: { ! 393: struct passwd *pwdinfo; /* password info structure */ ! 394: char *logname, *getlogin(); ! 395: ! 396: ! 397: logname = getlogin(); ! 398: if (logname == NULL || (pwdinfo = getpwnam(logname)) == NULL || ! 399: pwdinfo->pw_uid != uid) ! 400: pwdinfo = getpwuid(uid); ! 401: if (pwdinfo == 0) { ! 402: fprintf(stderr, "no name for uid %d?\n", uid); ! 403: exit(1); ! 404: } ! 405: return(pwdinfo->pw_name); ! 406: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.