1: /*	lprm.c	4.3	81/08/06	*/
   2: /*
   3:  * lprm - dequeue the current user's spool entry
   4:  *
   5:  * lprm [-] [pid] [user]
   6:  *
   7:  * Using information in the lock file, lprm will kill the
   8:  * currently active daemon (if necessary), remove the associated files,
   9:  * startup a new daemon.  Priviledged users may remove anyone's spool
  10:  * entries, otherwise one can only remove their own.
  11:  *
  12:  */
  13: 
  14: #include    <stdio.h>
  15: #include    <signal.h>
  16: #include    <sys/types.h>
  17: #include    <sys/dir.h>
  18: #include    <pwd.h>
  19: #include    <sys/stat.h>
  20: #include    <ctype.h>
  21: #include    <errno.h>
  22: #include    "lp.local.h"
  23: 
  24: #define MAXUSERS    50
  25: #define MAXREQUESTS 30
  26: 
  27: /*
  28:  * Stuff for handling lprm specifications
  29:  */
  30: struct  passwd  user[MAXUSERS];     /* users to process */
  31: struct  direct  *pdir;          /* used in perusing SPOOLDIR */
  32: int     users;          /* # of users in user array */
  33: int     cur_daemon;     /* daemon's pid */
  34: int     cur_pid;        /* active daemon file pid */
  35: int     requ[MAXREQUESTS];  /* pid of spool entries */
  36: int     requests;       /* # of spool requests */
  37: int     all = 0;        /* eliminate everything ? */
  38: 
  39: /*
  40:  * Stuff for printcap (a la termcap) description
  41:  */
  42: char    *SD;
  43: char    *LO;
  44: char    *DN;
  45: char    *AF;
  46: char    *printer;
  47: char    *pgetstr();
  48: 
  49: struct passwd *getpwnam(), *getpwuid();
  50: char    *malloc();
  51: char    *realloc();
  52: char    *getenv();
  53: char    *malloc();
  54: char    *rindex();
  55: 
  56: main(argc, argv)
  57:     char *argv[];
  58: {
  59:     register int nitems, garbage = 0;
  60:     register struct passwd *p;
  61:     register int nargs = argc;
  62:     int assasinated = 0;
  63: 
  64:     argv++;
  65:     while (argc > 1) {
  66:         if (argv[0][0] == '-') {
  67:             if (argv[0][1] == 'P') {
  68:                 if (!chkprinter(&argv[0][2]))
  69:                     fatal("%s: unknown printer", &argv[0][2]);
  70:                 printer = &argv[0][2];
  71:             } else {
  72:                 if (users)
  73:                     usage();
  74:                 users = -1;
  75:             }
  76:         } else {
  77:             if (users < 0)
  78:                 usage();
  79:             if (isdigit(argv[0][0])) {
  80:                 if (requests >= MAXREQUESTS)
  81:                     fatal("too many requests to lprm");
  82:                 requ[requests++] = atoi(*argv);
  83:             } else {
  84:                 if (users >= MAXUSERS)
  85:                     fatal("too many users");
  86:                 p = getpwnam(*argv);
  87:                 if (p)
  88:                     user[users++] = *p;
  89:                 else
  90:                     fatal("%s: unknown user", *argv);
  91:             }
  92:         }
  93:         argc--;
  94:         argv++;
  95:     }
  96:     /*
  97: 	 * If the format was `lprm -' and the user isn't super-user,
  98: 	 *  then fake things to look like he said `lprm user'.
  99: 	 */
 100:     if (users < 0) {
 101:         int uid;
 102: 
 103:         if ((uid = getuid()) != 0) {
 104:             if ((p = getpwuid(uid)) == NULL)
 105:                 fatal("who are you?");
 106:             user[0] = *p;
 107:             users = 1;
 108:         } else
 109:             all = 1;
 110:     }
 111:     /*
 112: 	 * Build a picture of the spool q
 113: 	 */
 114:     if (printer == NULL) {
 115:         if ((printer = getenv("PRINTER")) == NULL)
 116:             printer = DEFLP;
 117:         if (!chkprinter(printer))
 118:             fatal("%s: unknown printer", printer);
 119:     }
 120:     if (chdir(SD) < 0)
 121:         fatal("can't chdir to spooling area");
 122:     if ((nitems = collect()) == 0) {
 123:         printf("no entries\n");
 124:         exit(0);
 125:     }
 126:     garbage = lockchk(LO);
 127:     /*
 128: 	 * If we have garbage, then just remove the files,
 129: 	 *  otherwise check first for an active daemon
 130: 	 *  (in which case we kill it off it is reading our file)
 131: 	 *  then remove stuff (after which we have to restart the
 132: 	 *  daemon).
 133: 	 */
 134:     if (!garbage) {
 135:         char file[15];
 136: 
 137:         sprintf(file, "dfA%05d", cur_pid);
 138: #ifndef UNM
 139:         if ((nargs == 1 && access(file, 4) == 0) || chk(file, cur_pid)) {
 140: #else   UNM
 141:         if ((nargs == 1 && access(file, 2) == 0) || chk(file, cur_pid)) {
 142: #endif	UNM
 143:             requ[requests++] = cur_pid;
 144:             assasinated = (kill(cur_daemon, SIGTERM) == 0);
 145:             if (!assasinated)
 146:                 fatal("can't kill daemon");
 147:         }
 148:     }
 149:     for (nargs = 0; nargs < nitems; nargs++)
 150:         process(&pdir[nargs]);
 151:     if (!garbage && assasinated) {
 152:         unlink(LO);
 153:         execl(DN, rindex(DN, '/') ? rindex(DN, '/')+1 : DN, printer, 0);
 154:         fatal("can't restart daemon");
 155:     }
 156: }
 157: 
 158: /*
 159:  * Process a lock file: collect the pid of the active
 160:  *  daemon and the pid of the active spool entry.
 161:  * Return boolean indicating non-existence of a lock file.
 162:  */
 163: lockchk(s)
 164:     char *s;
 165: {
 166:     register int fd;
 167:     register int i;
 168:     extern int errno;
 169: 
 170:     if ((fd = open(s, 0)) < 0)
 171:         if (errno == EACCES)
 172:             fatal("can't access lock file");
 173:         else
 174:             return(1);
 175:     if (read(fd, (char *)&cur_daemon, sizeof(int)) != sizeof(int))
 176:         fatal("bad lock file (daemon pid)");
 177:     for (i = 1; read(fd, (char *)&cur_pid, sizeof(int)) != sizeof(int); i++) {
 178:         if (i > 20) {
 179:             cur_pid = -1;       /* choose impossible pid */
 180:             break;
 181:         }
 182:         sleep(i);
 183:     }
 184:     close(fd);
 185:     return(0);
 186: }
 187: 
 188: /*
 189:  * Process the spool q: build an in-core table of the directory
 190:  *  for use in deciding what gets removed.
 191:  */
 192: collect()
 193: {
 194:     register int fd, items = 0;
 195:     register char c1, c2;
 196:     struct direct proto;
 197: 
 198:     if ((fd = open(".", 0)) < 0)
 199:         fatal("can't access spooling directory");
 200:     /*
 201: 	 * skip . and ..
 202: 	 */
 203:     lseek(fd, (long)(2*sizeof(struct direct)), 0);
 204:     pdir = (struct direct *)malloc(sizeof(struct direct));
 205:     while(1) {
 206:         register struct direct *proto;
 207: 
 208:         proto = &pdir[items];
 209:         if (read(fd, (char *)proto, sizeof(*proto)) != sizeof(*proto))
 210:             break;
 211:         if (proto->d_ino == 0)
 212:             continue;
 213:         c1 = proto->d_name[0], c2 = proto->d_name[1];
 214:         if (c1 != 't' && c1 != 'c' && c1 != 'd' && c1 != 'l')
 215:             continue;
 216:         if (c2 != 'f')
 217:             continue;
 218:         items++;
 219:         proto = (struct direct *)realloc((char *)pdir, (items+1)*sizeof(struct direct));
 220:         if (proto == NULL) {
 221:             printf("out of memory, only handling %d items\n", items);
 222:             break;
 223:         }
 224:         pdir = proto;
 225:     }
 226:     return(items);
 227: }
 228: 
 229: /*
 230:  * Check through the requests and users to see if this
 231:  * directory entry should be removed.
 232:  */
 233: process(p)
 234:     register struct direct *p;
 235: {
 236:     if (all || chk(p->d_name, atoi(p->d_name+3)))
 237:         printf(unlink(p->d_name) ? "can't dequeue %s\n" : "%s dequeued\n",
 238:             p->d_name);
 239: }
 240: /*
 241:  * Do the dirty work in checking
 242:  */
 243: chk(file, pid)
 244:     char *file;
 245:     int pid;
 246: {
 247:     struct stat buf;
 248:     register struct passwd *q;
 249:     register int *r;
 250: 
 251:     /*
 252: 	 * Check the request list
 253: 	 */
 254:     for (r = requ; r < &requ[requests]; r++)
 255: #ifndef UNM
 256:         if (*r == pid && access(file, 4) == 0)
 257: #else   UNM
 258:         if (*r == pid && access(file, 2) == 0)
 259: #endif	UNM
 260:             return(1);
 261:     if (stat(file, &buf) < 0)
 262:         return(0);
 263:     /*
 264: 	 * Check to see if it's in the user list
 265: 	 */
 266:     for (q = user; q < &user[users]; q++)
 267: #ifndef UNM
 268:         if (q->pw_uid == buf.st_uid && access(file, 4) == 0)
 269: #else   UNM
 270:         if (q->pw_uid == buf.st_uid && access(file, 2) == 0)
 271: #endif	UNM
 272:             return(1);
 273:     return(0);
 274: }
 275: 
 276: fatal(s, a)
 277:     char *s, *a;
 278: {
 279:     fprintf(stderr, "lprm: fatal error: ");
 280:     fprintf(stderr, s, a);
 281:     fputc('\n', stderr);
 282:     exit(1);
 283: }
 284: 
 285: usage()
 286: {
 287:     printf("usage: lprm [-] [-Pprinter] [[job #] [user] ...]\n");
 288:     exit(2);
 289: }
 290: 
 291: chkprinter(s)
 292: char *s;
 293: {
 294:     static char buf[BUFSIZ/2];
 295:     char b[BUFSIZ];
 296:     int stat;
 297:     char *bp = buf;
 298: 
 299:     if ((stat = pgetent(b, s)) < 0)
 300:         fatal("can't open description file");
 301:     else if (stat == 0)
 302:         return(0);
 303:     if ((DN = pgetstr("dn", &bp)) == NULL)
 304:         DN = DEFDAEMON;
 305:     if ((SD = pgetstr("sd", &bp)) == NULL)
 306:         SD = DEFSPOOL;
 307:     if ((LO = pgetstr("lo", &bp)) == NULL)
 308:         LO = DEFLOCK;
 309:     AF = pgetstr("af", &bp);
 310:     return(1);
 311: }

Defined functions

chk defined in line 243; used 3 times
chkprinter defined in line 291; used 2 times
collect defined in line 192; used 1 times
fatal defined in line 276; used 13 times
lockchk defined in line 163; used 1 times
main defined in line 56; never used
process defined in line 233; used 1 times
usage defined in line 285; used 2 times

Defined variables

AF defined in line 45; used 1 times
DN defined in line 44; used 6 times
LO defined in line 43; used 4 times
SD defined in line 42; used 3 times
all defined in line 37; used 2 times
cur_daemon defined in line 33; used 2 times
cur_pid defined in line 34; used 6 times
pdir defined in line 31; used 5 times
printer defined in line 46; used 7 times
requ defined in line 35; used 4 times
requests defined in line 36; used 4 times
user defined in line 30; used 4 times
users defined in line 32; used 8 times

Defined macros

MAXREQUESTS defined in line 25; used 2 times
MAXUSERS defined in line 24; used 2 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 896
Valid CSS Valid XHTML 1.0 Strict