122424Sdist /* 222424Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 542801Sbostic * %sccs.include.redist.c% 622424Sdist */ 722424Sdist 812382Sralph #ifndef lint 9*55472Sbostic static char sccsid[] = "@(#)cmds.c 5.8 (Berkeley) 07/21/92"; 1034203Sbostic #endif /* not lint */ 1112382Sralph 1212382Sralph /* 1315719Sralph * lpc -- line printer control program -- commands: 1412382Sralph */ 1512382Sralph 16*55472Sbostic #include <sys/param.h> 17*55472Sbostic #include <sys/time.h> 18*55472Sbostic #include <sys/stat.h> 19*55472Sbostic 20*55472Sbostic #include <signal.h> 21*55472Sbostic #include <fcntl.h> 22*55472Sbostic #include <errno.h> 23*55472Sbostic #include <dirent.h> 24*55472Sbostic #include <unistd.h> 25*55472Sbostic #include <stdlib.h> 26*55472Sbostic #include <stdio.h> 27*55472Sbostic #include <ctype.h> 28*55472Sbostic #include <string.h> 2912382Sralph #include "lp.h" 30*55472Sbostic #include "lp.local.h" 31*55472Sbostic #include "lpc.h" 32*55472Sbostic #include "extern.h" 3337968Sbostic #include "pathnames.h" 3412382Sralph 35*55472Sbostic static void abortpr __P((int)); 36*55472Sbostic static void cleanpr __P((void)); 37*55472Sbostic static int doselect __P((struct dirent *)); 38*55472Sbostic static void upstat __P((char *)); 39*55472Sbostic static int sortq __P((const void *, const void *)); 40*55472Sbostic static void unlinkf __P((char *)); 41*55472Sbostic static int doarg __P((char *)); 42*55472Sbostic static int touch __P((struct queue *)); 43*55472Sbostic static void stoppr __P((void)); 44*55472Sbostic static void prstat __P((void)); 45*55472Sbostic static void startpr __P((int)); 46*55472Sbostic static void putmsg __P((int, char **)); 47*55472Sbostic static void disablepr __P((void)); 48*55472Sbostic static void enablepr __P((void)); 49*55472Sbostic 50*55472Sbostic 5112382Sralph /* 5212382Sralph * kill an existing daemon and disable printing. 5312382Sralph */ 54*55472Sbostic void 55*55472Sbostic doabort(argc, argv) 56*55472Sbostic int argc; 5712382Sralph char *argv[]; 5812382Sralph { 5912382Sralph register int c, status; 6012382Sralph register char *cp1, *cp2; 6112382Sralph char prbuf[100]; 6212382Sralph 6312382Sralph if (argc == 1) { 6412382Sralph printf("Usage: abort {all | printer ...}\n"); 6512382Sralph return; 6612382Sralph } 6712382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 6812382Sralph printer = prbuf; 6912382Sralph while (getprent(line) > 0) { 7012382Sralph cp1 = prbuf; 7112382Sralph cp2 = line; 7212382Sralph while ((c = *cp2++) && c != '|' && c != ':') 7312382Sralph *cp1++ = c; 7412382Sralph *cp1 = '\0'; 7516755Sralph abortpr(1); 7612382Sralph } 7712382Sralph return; 7812382Sralph } 7912382Sralph while (--argc) { 8012382Sralph printer = *++argv; 8112382Sralph if ((status = pgetent(line, printer)) < 0) { 8212514Sralph printf("cannot open printer description file\n"); 8312382Sralph continue; 8412382Sralph } else if (status == 0) { 8512514Sralph printf("unknown printer %s\n", printer); 8612382Sralph continue; 8712382Sralph } 8816755Sralph abortpr(1); 8912382Sralph } 9012382Sralph } 9112382Sralph 92*55472Sbostic static void 9316755Sralph abortpr(dis) 94*55472Sbostic int dis; 9512382Sralph { 9612382Sralph register FILE *fp; 9712382Sralph struct stat stbuf; 9812382Sralph int pid, fd; 9912382Sralph 10012382Sralph bp = pbuf; 10112382Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 10237968Sbostic SD = _PATH_DEFSPOOL; 10312382Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 10412382Sralph LO = DEFLOCK; 10512382Sralph (void) sprintf(line, "%s/%s", SD, LO); 10612382Sralph printf("%s:\n", printer); 10712382Sralph 10812382Sralph /* 10912382Sralph * Turn on the owner execute bit of the lock file to disable printing. 11012382Sralph */ 11116755Sralph if (dis) { 11216755Sralph if (stat(line, &stbuf) >= 0) { 11316755Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 11416755Sralph printf("\tcannot disable printing\n"); 11538735Stef else { 11638735Stef upstat("printing disabled\n"); 11716755Sralph printf("\tprinting disabled\n"); 11838735Stef } 11916755Sralph } else if (errno == ENOENT) { 12016755Sralph if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 12116755Sralph printf("\tcannot create lock file\n"); 12216755Sralph else { 12316755Sralph (void) close(fd); 12438735Stef upstat("printing disabled\n"); 12516755Sralph printf("\tprinting disabled\n"); 12616755Sralph printf("\tno daemon to abort\n"); 12716755Sralph } 12816755Sralph return; 12916755Sralph } else { 13016755Sralph printf("\tcannot stat lock file\n"); 13116755Sralph return; 13212382Sralph } 13312382Sralph } 13412382Sralph /* 13512382Sralph * Kill the current daemon to stop printing now. 13612382Sralph */ 13712382Sralph if ((fp = fopen(line, "r")) == NULL) { 13812382Sralph printf("\tcannot open lock file\n"); 13912382Sralph return; 14012382Sralph } 14113146Ssam if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 14213168Sralph (void) fclose(fp); /* unlocks as well */ 14312382Sralph printf("\tno daemon to abort\n"); 14412382Sralph return; 14512382Sralph } 14612382Sralph (void) fclose(fp); 14716755Sralph if (kill(pid = atoi(line), SIGTERM) < 0) 14812382Sralph printf("\tWarning: daemon (pid %d) not killed\n", pid); 14912382Sralph else 15012382Sralph printf("\tdaemon (pid %d) killed\n", pid); 15112382Sralph } 15212382Sralph 15312382Sralph /* 15438735Stef * Write a message into the status file. 15538735Stef */ 156*55472Sbostic static void 15738735Stef upstat(msg) 15838735Stef char *msg; 15938735Stef { 16038735Stef register int fd; 16138735Stef char statfile[BUFSIZ]; 16238735Stef 16338735Stef bp = pbuf; 16438735Stef if ((ST = pgetstr("st", &bp)) == NULL) 16538735Stef ST = DEFSTAT; 16638735Stef (void) sprintf(statfile, "%s/%s", SD, ST); 16738735Stef umask(0); 16838735Stef fd = open(statfile, O_WRONLY|O_CREAT, 0664); 16938735Stef if (fd < 0 || flock(fd, LOCK_EX) < 0) { 17038735Stef printf("\tcannot create status file\n"); 17138735Stef return; 17238735Stef } 17338735Stef (void) ftruncate(fd, 0); 17438735Stef if (msg == (char *)NULL) 17538735Stef (void) write(fd, "\n", 1); 17638735Stef else 17738735Stef (void) write(fd, msg, strlen(msg)); 17838735Stef (void) close(fd); 17938735Stef } 18038735Stef 18138735Stef /* 18212382Sralph * Remove all spool files and temporaries from the spooling area. 18312382Sralph */ 184*55472Sbostic void 18512382Sralph clean(argc, argv) 186*55472Sbostic int argc; 18712382Sralph char *argv[]; 18812382Sralph { 18912382Sralph register int c, status; 19012382Sralph register char *cp1, *cp2; 19112382Sralph char prbuf[100]; 19212382Sralph 19312382Sralph if (argc == 1) { 19412382Sralph printf("Usage: clean {all | printer ...}\n"); 19512382Sralph return; 19612382Sralph } 19712382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 19812382Sralph printer = prbuf; 19912382Sralph while (getprent(line) > 0) { 20012382Sralph cp1 = prbuf; 20112382Sralph cp2 = line; 20212382Sralph while ((c = *cp2++) && c != '|' && c != ':') 20312382Sralph *cp1++ = c; 20412382Sralph *cp1 = '\0'; 20512382Sralph cleanpr(); 20612382Sralph } 20712382Sralph return; 20812382Sralph } 20912382Sralph while (--argc) { 21012382Sralph printer = *++argv; 21112382Sralph if ((status = pgetent(line, printer)) < 0) { 21212514Sralph printf("cannot open printer description file\n"); 21312382Sralph continue; 21412382Sralph } else if (status == 0) { 21512514Sralph printf("unknown printer %s\n", printer); 21612382Sralph continue; 21712382Sralph } 21812382Sralph cleanpr(); 21912382Sralph } 22012382Sralph } 22112382Sralph 222*55472Sbostic static int 223*55472Sbostic doselect(d) 224*55472Sbostic struct dirent *d; 22515719Sralph { 22615719Sralph int c = d->d_name[0]; 22715719Sralph 22815719Sralph if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 22915719Sralph return(1); 23015719Sralph return(0); 23115719Sralph } 23215719Sralph 23315719Sralph /* 23415719Sralph * Comparison routine for scandir. Sort by job number and machine, then 23515719Sralph * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 23615719Sralph */ 237*55472Sbostic static int 238*55472Sbostic sortq(a, b) 239*55472Sbostic const void *a, *b; 24015719Sralph { 241*55472Sbostic struct dirent **d1, **d2; 24215719Sralph int c1, c2; 24315719Sralph 244*55472Sbostic d1 = (struct dirent **)a; 245*55472Sbostic d2 = (struct dirent **)b; 24615719Sralph if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) 24715719Sralph return(c1); 24815719Sralph c1 = (*d1)->d_name[0]; 24915719Sralph c2 = (*d2)->d_name[0]; 25015719Sralph if (c1 == c2) 25115719Sralph return((*d1)->d_name[2] - (*d2)->d_name[2]); 25215719Sralph if (c1 == 'c') 25315719Sralph return(-1); 25415719Sralph if (c1 == 'd' || c2 == 'c') 25515719Sralph return(1); 25615719Sralph return(-1); 25715719Sralph } 25815719Sralph 25915719Sralph /* 26015719Sralph * Remove incomplete jobs from spooling area. 26115719Sralph */ 262*55472Sbostic static void 26312382Sralph cleanpr() 26412382Sralph { 26515719Sralph register int i, n; 26615719Sralph register char *cp, *cp1, *lp; 267*55472Sbostic struct dirent **queue; 26815719Sralph int nitems; 26912382Sralph 27012382Sralph bp = pbuf; 27112382Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 27237968Sbostic SD = _PATH_DEFSPOOL; 27312382Sralph printf("%s:\n", printer); 27412382Sralph 27515719Sralph for (lp = line, cp = SD; *lp++ = *cp++; ) 27615719Sralph ; 27715719Sralph lp[-1] = '/'; 27815719Sralph 279*55472Sbostic nitems = scandir(SD, &queue, doselect, sortq); 28015719Sralph if (nitems < 0) { 28112382Sralph printf("\tcannot examine spool directory\n"); 28212382Sralph return; 28312382Sralph } 28415719Sralph if (nitems == 0) 28515719Sralph return; 28615719Sralph i = 0; 28715719Sralph do { 28815719Sralph cp = queue[i]->d_name; 28915719Sralph if (*cp == 'c') { 29015719Sralph n = 0; 29115719Sralph while (i + 1 < nitems) { 29215719Sralph cp1 = queue[i + 1]->d_name; 29315719Sralph if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 29415719Sralph break; 29515719Sralph i++; 29615719Sralph n++; 29715719Sralph } 29815719Sralph if (n == 0) { 29915719Sralph strcpy(lp, cp); 30015719Sralph unlinkf(line); 30115719Sralph } 30215719Sralph } else { 30315719Sralph /* 30415719Sralph * Must be a df with no cf (otherwise, it would have 30515719Sralph * been skipped above) or a tf file (which can always 30615719Sralph * be removed). 30715719Sralph */ 30815719Sralph strcpy(lp, cp); 30915719Sralph unlinkf(line); 31012382Sralph } 31115719Sralph } while (++i < nitems); 31212382Sralph } 31315719Sralph 314*55472Sbostic static void 31515719Sralph unlinkf(name) 31615719Sralph char *name; 31715719Sralph { 31815719Sralph if (unlink(name) < 0) 31915719Sralph printf("\tcannot remove %s\n", name); 32015719Sralph else 32115719Sralph printf("\tremoved %s\n", name); 32215719Sralph } 32312382Sralph 32412382Sralph /* 32512382Sralph * Enable queuing to the printer (allow lpr's). 32612382Sralph */ 327*55472Sbostic void 32812382Sralph enable(argc, argv) 329*55472Sbostic int argc; 33012382Sralph char *argv[]; 33112382Sralph { 33212382Sralph register int c, status; 33312382Sralph register char *cp1, *cp2; 33412382Sralph char prbuf[100]; 33512382Sralph 33612382Sralph if (argc == 1) { 33712382Sralph printf("Usage: enable {all | printer ...}\n"); 33812382Sralph return; 33912382Sralph } 34012382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 34112382Sralph printer = prbuf; 34212382Sralph while (getprent(line) > 0) { 34312382Sralph cp1 = prbuf; 34412382Sralph cp2 = line; 34512382Sralph while ((c = *cp2++) && c != '|' && c != ':') 34612382Sralph *cp1++ = c; 34712382Sralph *cp1 = '\0'; 34812382Sralph enablepr(); 34912382Sralph } 35012382Sralph return; 35112382Sralph } 35212382Sralph while (--argc) { 35312382Sralph printer = *++argv; 35412382Sralph if ((status = pgetent(line, printer)) < 0) { 35512514Sralph printf("cannot open printer description file\n"); 35612382Sralph continue; 35712382Sralph } else if (status == 0) { 35812514Sralph printf("unknown printer %s\n", printer); 35912382Sralph continue; 36012382Sralph } 36112382Sralph enablepr(); 36212382Sralph } 36312382Sralph } 36412382Sralph 365*55472Sbostic static void 36612382Sralph enablepr() 36712382Sralph { 36812382Sralph struct stat stbuf; 36912382Sralph 37012382Sralph bp = pbuf; 37112382Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 37237968Sbostic SD = _PATH_DEFSPOOL; 37312382Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 37412382Sralph LO = DEFLOCK; 37512382Sralph (void) sprintf(line, "%s/%s", SD, LO); 37612382Sralph printf("%s:\n", printer); 37712382Sralph 37812382Sralph /* 37912382Sralph * Turn off the group execute bit of the lock file to enable queuing. 38012382Sralph */ 38112382Sralph if (stat(line, &stbuf) >= 0) { 38212382Sralph if (chmod(line, stbuf.st_mode & 0767) < 0) 38312514Sralph printf("\tcannot enable queuing\n"); 38412382Sralph else 38512382Sralph printf("\tqueuing enabled\n"); 38612382Sralph } 38712382Sralph } 38812382Sralph 38912382Sralph /* 39012382Sralph * Disable queuing. 39112382Sralph */ 392*55472Sbostic void 39312382Sralph disable(argc, argv) 394*55472Sbostic int argc; 39512382Sralph char *argv[]; 39612382Sralph { 39712382Sralph register int c, status; 39812382Sralph register char *cp1, *cp2; 39912382Sralph char prbuf[100]; 40012382Sralph 40112382Sralph if (argc == 1) { 40212382Sralph printf("Usage: disable {all | printer ...}\n"); 40312382Sralph return; 40412382Sralph } 40512382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 40612382Sralph printer = prbuf; 40712382Sralph while (getprent(line) > 0) { 40812382Sralph cp1 = prbuf; 40912382Sralph cp2 = line; 41012382Sralph while ((c = *cp2++) && c != '|' && c != ':') 41112382Sralph *cp1++ = c; 41212382Sralph *cp1 = '\0'; 41312382Sralph disablepr(); 41412382Sralph } 41512382Sralph return; 41612382Sralph } 41712382Sralph while (--argc) { 41812382Sralph printer = *++argv; 41912382Sralph if ((status = pgetent(line, printer)) < 0) { 42012514Sralph printf("cannot open printer description file\n"); 42112382Sralph continue; 42212382Sralph } else if (status == 0) { 42312514Sralph printf("unknown printer %s\n", printer); 42412382Sralph continue; 42512382Sralph } 42612382Sralph disablepr(); 42712382Sralph } 42812382Sralph } 42912382Sralph 430*55472Sbostic static void 43112382Sralph disablepr() 43212382Sralph { 43312382Sralph register int fd; 43412382Sralph struct stat stbuf; 43512382Sralph 43612382Sralph bp = pbuf; 43712382Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 43837968Sbostic SD = _PATH_DEFSPOOL; 43912382Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 44012382Sralph LO = DEFLOCK; 44112382Sralph (void) sprintf(line, "%s/%s", SD, LO); 44212382Sralph printf("%s:\n", printer); 44312382Sralph /* 44412382Sralph * Turn on the group execute bit of the lock file to disable queuing. 44512382Sralph */ 44612382Sralph if (stat(line, &stbuf) >= 0) { 44712382Sralph if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) 44812382Sralph printf("\tcannot disable queuing\n"); 44912382Sralph else 45012382Sralph printf("\tqueuing disabled\n"); 45112382Sralph } else if (errno == ENOENT) { 45213146Ssam if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) 45312382Sralph printf("\tcannot create lock file\n"); 45412382Sralph else { 45512382Sralph (void) close(fd); 45612382Sralph printf("\tqueuing disabled\n"); 45712382Sralph } 45812382Sralph return; 45912382Sralph } else 46012382Sralph printf("\tcannot stat lock file\n"); 46112382Sralph } 46212382Sralph 46312382Sralph /* 46415907Sralph * Disable queuing and printing and put a message into the status file 46515907Sralph * (reason for being down). 46615907Sralph */ 467*55472Sbostic void 46815907Sralph down(argc, argv) 469*55472Sbostic int argc; 47015907Sralph char *argv[]; 47115907Sralph { 47215907Sralph register int c, status; 47315907Sralph register char *cp1, *cp2; 47415907Sralph char prbuf[100]; 47515907Sralph 47615907Sralph if (argc == 1) { 47716204Sralph printf("Usage: down {all | printer} [message ...]\n"); 47815907Sralph return; 47915907Sralph } 48015907Sralph if (!strcmp(argv[1], "all")) { 48115907Sralph printer = prbuf; 48215907Sralph while (getprent(line) > 0) { 48315907Sralph cp1 = prbuf; 48415907Sralph cp2 = line; 48515907Sralph while ((c = *cp2++) && c != '|' && c != ':') 48615907Sralph *cp1++ = c; 48715907Sralph *cp1 = '\0'; 48815907Sralph putmsg(argc - 2, argv + 2); 48915907Sralph } 49015907Sralph return; 49115907Sralph } 49215907Sralph printer = argv[1]; 49315907Sralph if ((status = pgetent(line, printer)) < 0) { 49415907Sralph printf("cannot open printer description file\n"); 49515907Sralph return; 49615907Sralph } else if (status == 0) { 49715907Sralph printf("unknown printer %s\n", printer); 49815907Sralph return; 49915907Sralph } 50015907Sralph putmsg(argc - 2, argv + 2); 50115907Sralph } 50215907Sralph 503*55472Sbostic static void 50415907Sralph putmsg(argc, argv) 505*55472Sbostic int argc; 50615907Sralph char **argv; 50715907Sralph { 50815907Sralph register int fd; 50915907Sralph register char *cp1, *cp2; 51015907Sralph char buf[1024]; 51115907Sralph struct stat stbuf; 51215907Sralph 51315907Sralph bp = pbuf; 51415907Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 51537968Sbostic SD = _PATH_DEFSPOOL; 51615907Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 51715907Sralph LO = DEFLOCK; 51815907Sralph if ((ST = pgetstr("st", &bp)) == NULL) 51915907Sralph ST = DEFSTAT; 52015907Sralph printf("%s:\n", printer); 52115907Sralph /* 52215907Sralph * Turn on the group execute bit of the lock file to disable queuing and 52315907Sralph * turn on the owner execute bit of the lock file to disable printing. 52415907Sralph */ 52515907Sralph (void) sprintf(line, "%s/%s", SD, LO); 52615907Sralph if (stat(line, &stbuf) >= 0) { 52715907Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0) 52815907Sralph printf("\tcannot disable queuing\n"); 52915907Sralph else 53015907Sralph printf("\tprinter and queuing disabled\n"); 53115907Sralph } else if (errno == ENOENT) { 53215907Sralph if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0) 53315907Sralph printf("\tcannot create lock file\n"); 53415907Sralph else { 53515907Sralph (void) close(fd); 53615907Sralph printf("\tprinter and queuing disabled\n"); 53715907Sralph } 53815907Sralph return; 53915907Sralph } else 54015907Sralph printf("\tcannot stat lock file\n"); 54115907Sralph /* 54215907Sralph * Write the message into the status file. 54315907Sralph */ 54415907Sralph (void) sprintf(line, "%s/%s", SD, ST); 54515907Sralph fd = open(line, O_WRONLY|O_CREAT, 0664); 54615907Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 54715907Sralph printf("\tcannot create status file\n"); 54815907Sralph return; 54915907Sralph } 55015907Sralph (void) ftruncate(fd, 0); 55116204Sralph if (argc <= 0) { 55216204Sralph (void) write(fd, "\n", 1); 55316204Sralph (void) close(fd); 55416204Sralph return; 55516204Sralph } 55615907Sralph cp1 = buf; 55715907Sralph while (--argc >= 0) { 55815907Sralph cp2 = *argv++; 55915907Sralph while (*cp1++ = *cp2++) 56015907Sralph ; 56115907Sralph cp1[-1] = ' '; 56215907Sralph } 56315907Sralph cp1[-1] = '\n'; 56415907Sralph *cp1 = '\0'; 56515907Sralph (void) write(fd, buf, strlen(buf)); 56615907Sralph (void) close(fd); 56715907Sralph } 56815907Sralph 56915907Sralph /* 57012382Sralph * Exit lpc 57112382Sralph */ 572*55472Sbostic void 57312382Sralph quit(argc, argv) 574*55472Sbostic int argc; 57512382Sralph char *argv[]; 57612382Sralph { 57712382Sralph exit(0); 57812382Sralph } 57912382Sralph 58012382Sralph /* 58116755Sralph * Kill and restart the daemon. 58212382Sralph */ 583*55472Sbostic void 58412382Sralph restart(argc, argv) 585*55472Sbostic int argc; 58612382Sralph char *argv[]; 58712382Sralph { 58812382Sralph register int c, status; 58912382Sralph register char *cp1, *cp2; 59012382Sralph char prbuf[100]; 59112382Sralph 59212382Sralph if (argc == 1) { 59312382Sralph printf("Usage: restart {all | printer ...}\n"); 59412382Sralph return; 59512382Sralph } 59612382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 59712382Sralph printer = prbuf; 59812382Sralph while (getprent(line) > 0) { 59912382Sralph cp1 = prbuf; 60012382Sralph cp2 = line; 60112382Sralph while ((c = *cp2++) && c != '|' && c != ':') 60212382Sralph *cp1++ = c; 60312382Sralph *cp1 = '\0'; 60416755Sralph abortpr(0); 60512382Sralph startpr(0); 60612382Sralph } 60712382Sralph return; 60812382Sralph } 60912382Sralph while (--argc) { 61012382Sralph printer = *++argv; 61112382Sralph if ((status = pgetent(line, printer)) < 0) { 61212514Sralph printf("cannot open printer description file\n"); 61312382Sralph continue; 61412382Sralph } else if (status == 0) { 61512514Sralph printf("unknown printer %s\n", printer); 61612382Sralph continue; 61712382Sralph } 61816755Sralph abortpr(0); 61912382Sralph startpr(0); 62012382Sralph } 62112382Sralph } 62212382Sralph 62312382Sralph /* 62412382Sralph * Enable printing on the specified printer and startup the daemon. 62512382Sralph */ 626*55472Sbostic void 62712382Sralph start(argc, argv) 628*55472Sbostic int argc; 62912382Sralph char *argv[]; 63012382Sralph { 63112382Sralph register int c, status; 63212382Sralph register char *cp1, *cp2; 63312382Sralph char prbuf[100]; 63412382Sralph 63512382Sralph if (argc == 1) { 63612382Sralph printf("Usage: start {all | printer ...}\n"); 63712382Sralph return; 63812382Sralph } 63912382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 64012382Sralph printer = prbuf; 64112382Sralph while (getprent(line) > 0) { 64212382Sralph cp1 = prbuf; 64312382Sralph cp2 = line; 64412382Sralph while ((c = *cp2++) && c != '|' && c != ':') 64512382Sralph *cp1++ = c; 64612382Sralph *cp1 = '\0'; 64712382Sralph startpr(1); 64812382Sralph } 64912382Sralph return; 65012382Sralph } 65112382Sralph while (--argc) { 65212382Sralph printer = *++argv; 65312382Sralph if ((status = pgetent(line, printer)) < 0) { 65412514Sralph printf("cannot open printer description file\n"); 65512382Sralph continue; 65612382Sralph } else if (status == 0) { 65712514Sralph printf("unknown printer %s\n", printer); 65812382Sralph continue; 65912382Sralph } 66012382Sralph startpr(1); 66112382Sralph } 66212382Sralph } 66312382Sralph 664*55472Sbostic static void 66512382Sralph startpr(enable) 666*55472Sbostic int enable; 66712382Sralph { 66812382Sralph struct stat stbuf; 66912382Sralph 67012382Sralph bp = pbuf; 67112382Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 67237968Sbostic SD = _PATH_DEFSPOOL; 67312382Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 67412382Sralph LO = DEFLOCK; 67512382Sralph (void) sprintf(line, "%s/%s", SD, LO); 67612382Sralph printf("%s:\n", printer); 67712382Sralph 67812382Sralph /* 67912382Sralph * Turn off the owner execute bit of the lock file to enable printing. 68012382Sralph */ 68112382Sralph if (enable && stat(line, &stbuf) >= 0) { 68216771Sralph if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0) 68312382Sralph printf("\tcannot enable printing\n"); 68412382Sralph else 68512382Sralph printf("\tprinting enabled\n"); 68612382Sralph } 68713727Sroot if (!startdaemon(printer)) 68812382Sralph printf("\tcouldn't start daemon\n"); 68912382Sralph else 69012382Sralph printf("\tdaemon started\n"); 69112382Sralph } 69212382Sralph 69312382Sralph /* 69412382Sralph * Print the status of each queue listed or all the queues. 69512382Sralph */ 696*55472Sbostic void 69712382Sralph status(argc, argv) 698*55472Sbostic int argc; 69912382Sralph char *argv[]; 70012382Sralph { 70112382Sralph register int c, status; 70212382Sralph register char *cp1, *cp2; 70312382Sralph char prbuf[100]; 70412382Sralph 70512382Sralph if (argc == 1) { 70612382Sralph printer = prbuf; 70712382Sralph while (getprent(line) > 0) { 70812382Sralph cp1 = prbuf; 70912382Sralph cp2 = line; 71012382Sralph while ((c = *cp2++) && c != '|' && c != ':') 71112382Sralph *cp1++ = c; 71212382Sralph *cp1 = '\0'; 71312382Sralph prstat(); 71412382Sralph } 71512382Sralph return; 71612382Sralph } 71712382Sralph while (--argc) { 71812382Sralph printer = *++argv; 71912382Sralph if ((status = pgetent(line, printer)) < 0) { 72012514Sralph printf("cannot open printer description file\n"); 72112382Sralph continue; 72212382Sralph } else if (status == 0) { 72312514Sralph printf("unknown printer %s\n", printer); 72412382Sralph continue; 72512382Sralph } 72612382Sralph prstat(); 72712382Sralph } 72812382Sralph } 72912382Sralph 73012382Sralph /* 73112382Sralph * Print the status of the printer queue. 73212382Sralph */ 733*55472Sbostic static void 73412382Sralph prstat() 73512382Sralph { 73612382Sralph struct stat stbuf; 73712382Sralph register int fd, i; 738*55472Sbostic register struct dirent *dp; 73912382Sralph DIR *dirp; 74012382Sralph 74112382Sralph bp = pbuf; 74212382Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 74337968Sbostic SD = _PATH_DEFSPOOL; 74412382Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 74512382Sralph LO = DEFLOCK; 74612382Sralph if ((ST = pgetstr("st", &bp)) == NULL) 74712382Sralph ST = DEFSTAT; 74812382Sralph printf("%s:\n", printer); 74912382Sralph (void) sprintf(line, "%s/%s", SD, LO); 75012382Sralph if (stat(line, &stbuf) >= 0) { 75112382Sralph printf("\tqueuing is %s\n", 75212382Sralph (stbuf.st_mode & 010) ? "disabled" : "enabled"); 75312382Sralph printf("\tprinting is %s\n", 75412382Sralph (stbuf.st_mode & 0100) ? "disabled" : "enabled"); 75512382Sralph } else { 75612382Sralph printf("\tqueuing is enabled\n"); 75712382Sralph printf("\tprinting is enabled\n"); 75812382Sralph } 75912382Sralph if ((dirp = opendir(SD)) == NULL) { 76012382Sralph printf("\tcannot examine spool directory\n"); 76112382Sralph return; 76212382Sralph } 76312382Sralph i = 0; 76412382Sralph while ((dp = readdir(dirp)) != NULL) { 76512382Sralph if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 76612382Sralph i++; 76712382Sralph } 76812382Sralph closedir(dirp); 76912382Sralph if (i == 0) 77012382Sralph printf("\tno entries\n"); 77112382Sralph else if (i == 1) 77212382Sralph printf("\t1 entry in spool area\n"); 77312382Sralph else 77412382Sralph printf("\t%d entries in spool area\n", i); 77513146Ssam fd = open(line, O_RDONLY); 77613146Ssam if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 77713168Sralph (void) close(fd); /* unlocks as well */ 77812382Sralph printf("\tno daemon present\n"); 77912382Sralph return; 78012382Sralph } 78112382Sralph (void) close(fd); 78212382Sralph putchar('\t'); 78312382Sralph (void) sprintf(line, "%s/%s", SD, ST); 78413146Ssam fd = open(line, O_RDONLY); 78513146Ssam if (fd >= 0) { 78613146Ssam (void) flock(fd, LOCK_SH); 78712382Sralph while ((i = read(fd, line, sizeof(line))) > 0) 78812382Sralph (void) fwrite(line, 1, i, stdout); 78913168Sralph (void) close(fd); /* unlocks as well */ 79012382Sralph } 79112382Sralph } 79212382Sralph 79312382Sralph /* 79412382Sralph * Stop the specified daemon after completing the current job and disable 79512382Sralph * printing. 79612382Sralph */ 797*55472Sbostic void 79812382Sralph stop(argc, argv) 799*55472Sbostic int argc; 80012382Sralph char *argv[]; 80112382Sralph { 80212382Sralph register int c, status; 80312382Sralph register char *cp1, *cp2; 80412382Sralph char prbuf[100]; 80512382Sralph 80612382Sralph if (argc == 1) { 80712382Sralph printf("Usage: stop {all | printer ...}\n"); 80812382Sralph return; 80912382Sralph } 81012382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 81112382Sralph printer = prbuf; 81212382Sralph while (getprent(line) > 0) { 81312382Sralph cp1 = prbuf; 81412382Sralph cp2 = line; 81512382Sralph while ((c = *cp2++) && c != '|' && c != ':') 81612382Sralph *cp1++ = c; 81712382Sralph *cp1 = '\0'; 81812382Sralph stoppr(); 81912382Sralph } 82012382Sralph return; 82112382Sralph } 82212382Sralph while (--argc) { 82312382Sralph printer = *++argv; 82412382Sralph if ((status = pgetent(line, printer)) < 0) { 82512514Sralph printf("cannot open printer description file\n"); 82612382Sralph continue; 82712382Sralph } else if (status == 0) { 82812514Sralph printf("unknown printer %s\n", printer); 82912382Sralph continue; 83012382Sralph } 83112382Sralph stoppr(); 83212382Sralph } 83312382Sralph } 83412382Sralph 835*55472Sbostic static void 83612382Sralph stoppr() 83712382Sralph { 83812382Sralph register int fd; 83912382Sralph struct stat stbuf; 84012382Sralph 84112382Sralph bp = pbuf; 84212382Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 84337968Sbostic SD = _PATH_DEFSPOOL; 84412382Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 84512382Sralph LO = DEFLOCK; 84612382Sralph (void) sprintf(line, "%s/%s", SD, LO); 84712382Sralph printf("%s:\n", printer); 84812382Sralph 84912382Sralph /* 85012382Sralph * Turn on the owner execute bit of the lock file to disable printing. 85112382Sralph */ 85212382Sralph if (stat(line, &stbuf) >= 0) { 85312382Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 85412382Sralph printf("\tcannot disable printing\n"); 85538735Stef else { 85638735Stef upstat("printing disabled\n"); 85712382Sralph printf("\tprinting disabled\n"); 85838735Stef } 85912382Sralph } else if (errno == ENOENT) { 86013146Ssam if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 86112382Sralph printf("\tcannot create lock file\n"); 86212382Sralph else { 86312382Sralph (void) close(fd); 86438735Stef upstat("printing disabled\n"); 86512382Sralph printf("\tprinting disabled\n"); 86612382Sralph } 86712382Sralph } else 86812382Sralph printf("\tcannot stat lock file\n"); 86912382Sralph } 87013727Sroot 87115719Sralph struct queue **queue; 87215719Sralph int nitems; 87315719Sralph time_t mtime; 87415719Sralph 87513727Sroot /* 87613727Sroot * Put the specified jobs at the top of printer queue. 87713727Sroot */ 878*55472Sbostic void 87913727Sroot topq(argc, argv) 880*55472Sbostic int argc; 88113727Sroot char *argv[]; 88213727Sroot { 883*55472Sbostic register int i; 88413727Sroot struct stat stbuf; 88515719Sralph int status, changed; 88613727Sroot 88715719Sralph if (argc < 3) { 88813727Sroot printf("Usage: topq printer [jobnum ...] [user ...]\n"); 88913727Sroot return; 89013727Sroot } 89113727Sroot 89213727Sroot --argc; 89313727Sroot printer = *++argv; 89413727Sroot status = pgetent(line, printer); 89513727Sroot if (status < 0) { 89613727Sroot printf("cannot open printer description file\n"); 89713727Sroot return; 89814151Sralph } else if (status == 0) { 89913727Sroot printf("%s: unknown printer\n", printer); 90013727Sroot return; 90113727Sroot } 90213727Sroot bp = pbuf; 90313727Sroot if ((SD = pgetstr("sd", &bp)) == NULL) 90437968Sbostic SD = _PATH_DEFSPOOL; 90513727Sroot if ((LO = pgetstr("lo", &bp)) == NULL) 90613727Sroot LO = DEFLOCK; 90713727Sroot printf("%s:\n", printer); 90813727Sroot 90913727Sroot if (chdir(SD) < 0) { 91013727Sroot printf("\tcannot chdir to %s\n", SD); 91113727Sroot return; 91213727Sroot } 91313727Sroot nitems = getq(&queue); 91415719Sralph if (nitems == 0) 91515719Sralph return; 91615719Sralph changed = 0; 91715719Sralph mtime = queue[0]->q_time; 91815719Sralph for (i = argc; --i; ) { 91915719Sralph if (doarg(argv[i]) == 0) { 92015719Sralph printf("\tjob %s is not in the queue\n", argv[i]); 92113727Sroot continue; 92215719Sralph } else 92314151Sralph changed++; 92413727Sroot } 92515719Sralph for (i = 0; i < nitems; i++) 92615719Sralph free(queue[i]); 92715719Sralph free(queue); 92815719Sralph if (!changed) { 92915719Sralph printf("\tqueue order unchanged\n"); 93015719Sralph return; 93113727Sroot } 93213727Sroot /* 93313727Sroot * Turn on the public execute bit of the lock file to 93413727Sroot * get lpd to rebuild the queue after the current job. 93513727Sroot */ 93614151Sralph if (changed && stat(LO, &stbuf) >= 0) 93714151Sralph (void) chmod(LO, (stbuf.st_mode & 0777) | 01); 93813727Sroot } 93913727Sroot 94015719Sralph /* 94115719Sralph * Reposition the job by changing the modification time of 94215719Sralph * the control file. 94313727Sroot */ 944*55472Sbostic static int 94515719Sralph touch(q) 94615719Sralph struct queue *q; 94713727Sroot { 94815719Sralph struct timeval tvp[2]; 94913727Sroot 95015719Sralph tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 95115719Sralph tvp[0].tv_usec = tvp[1].tv_usec = 0; 95215719Sralph return(utimes(q->q_name, tvp)); 95313727Sroot } 95413727Sroot 95513727Sroot /* 95613727Sroot * Checks if specified job name is in the printer's queue. 95713727Sroot * Returns: negative (-1) if argument name is not in the queue. 95813727Sroot */ 959*55472Sbostic static int 96015719Sralph doarg(job) 96113727Sroot char *job; 96213727Sroot { 96315719Sralph register struct queue **qq; 96415719Sralph register int jobnum, n; 96515719Sralph register char *cp, *machine; 96615719Sralph int cnt = 0; 96714151Sralph FILE *fp; 96813727Sroot 96915719Sralph /* 97015719Sralph * Look for a job item consisting of system name, colon, number 97115719Sralph * (example: ucbarpa:114) 97215719Sralph */ 97315719Sralph if ((cp = index(job, ':')) != NULL) { 97415719Sralph machine = job; 97515719Sralph *cp++ = '\0'; 97615719Sralph job = cp; 97715719Sralph } else 97815719Sralph machine = NULL; 97915719Sralph 98015719Sralph /* 98115719Sralph * Check for job specified by number (example: 112 or 235ucbarpa). 98215719Sralph */ 98313727Sroot if (isdigit(*job)) { 98413727Sroot jobnum = 0; 98513727Sroot do 98613727Sroot jobnum = jobnum * 10 + (*job++ - '0'); 98713727Sroot while (isdigit(*job)); 98815719Sralph for (qq = queue + nitems; --qq >= queue; ) { 98913727Sroot n = 0; 99015719Sralph for (cp = (*qq)->q_name+3; isdigit(*cp); ) 99114151Sralph n = n * 10 + (*cp++ - '0'); 99215719Sralph if (jobnum != n) 99315719Sralph continue; 99415719Sralph if (*job && strcmp(job, cp) != 0) 99515719Sralph continue; 99615719Sralph if (machine != NULL && strcmp(machine, cp) != 0) 99715719Sralph continue; 99815719Sralph if (touch(*qq) == 0) { 99915719Sralph printf("\tmoved %s\n", (*qq)->q_name); 100015719Sralph cnt++; 100115719Sralph } 100213727Sroot } 100315719Sralph return(cnt); 100415719Sralph } 100515719Sralph /* 100615719Sralph * Process item consisting of owner's name (example: henry). 100715719Sralph */ 100815719Sralph for (qq = queue + nitems; --qq >= queue; ) { 100915719Sralph if ((fp = fopen((*qq)->q_name, "r")) == NULL) 101013727Sroot continue; 101115719Sralph while (getline(fp) > 0) 101215719Sralph if (line[0] == 'P') 101315719Sralph break; 101415719Sralph (void) fclose(fp); 101515719Sralph if (line[0] != 'P' || strcmp(job, line+1) != 0) 101615719Sralph continue; 101715719Sralph if (touch(*qq) == 0) { 101815719Sralph printf("\tmoved %s\n", (*qq)->q_name); 101915719Sralph cnt++; 102013727Sroot } 102113727Sroot } 102215719Sralph return(cnt); 102313727Sroot } 102416755Sralph 102516755Sralph /* 102616755Sralph * Enable everything and start printer (undo `down'). 102716755Sralph */ 1028*55472Sbostic void 102916755Sralph up(argc, argv) 1030*55472Sbostic int argc; 103116755Sralph char *argv[]; 103216755Sralph { 103316755Sralph register int c, status; 103416755Sralph register char *cp1, *cp2; 103516755Sralph char prbuf[100]; 103616755Sralph 103716755Sralph if (argc == 1) { 103816755Sralph printf("Usage: up {all | printer ...}\n"); 103916755Sralph return; 104016755Sralph } 104116755Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 104216755Sralph printer = prbuf; 104316755Sralph while (getprent(line) > 0) { 104416755Sralph cp1 = prbuf; 104516755Sralph cp2 = line; 104616755Sralph while ((c = *cp2++) && c != '|' && c != ':') 104716755Sralph *cp1++ = c; 104816755Sralph *cp1 = '\0'; 104916755Sralph startpr(2); 105016755Sralph } 105116755Sralph return; 105216755Sralph } 105316755Sralph while (--argc) { 105416755Sralph printer = *++argv; 105516755Sralph if ((status = pgetent(line, printer)) < 0) { 105616755Sralph printf("cannot open printer description file\n"); 105716755Sralph continue; 105816755Sralph } else if (status == 0) { 105916755Sralph printf("unknown printer %s\n", printer); 106016755Sralph continue; 106116755Sralph } 106216755Sralph startpr(2); 106316755Sralph } 106416755Sralph } 1065