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