122424Sdist /* 222424Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*56121Selan * Redistribution and use in source and binary forms, with or without 6*56121Selan * modification, are permitted provided that the following conditions 7*56121Selan * are met: 8*56121Selan * 1. Redistributions of source code must retain the above copyright 9*56121Selan * notice, this list of conditions and the following disclaimer. 10*56121Selan * 2. Redistributions in binary form must reproduce the above copyright 11*56121Selan * notice, this list of conditions and the following disclaimer in the 12*56121Selan * documentation and/or other materials provided with the distribution. 13*56121Selan * 3. All advertising materials mentioning features or use of this software 14*56121Selan * must display the following acknowledgement: 15*56121Selan * This product includes software developed by the University of 16*56121Selan * California, Berkeley and its contributors. 17*56121Selan * 4. Neither the name of the University nor the names of its contributors 18*56121Selan * may be used to endorse or promote products derived from this software 19*56121Selan * without specific prior written permission. 20*56121Selan * 21*56121Selan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22*56121Selan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*56121Selan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*56121Selan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25*56121Selan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*56121Selan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*56121Selan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*56121Selan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*56121Selan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*56121Selan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*56121Selan * SUCH DAMAGE. 3222424Sdist */ 3322424Sdist 3412382Sralph #ifndef lint 35*56121Selan static char sccsid[] = "@(#)cmds.c 5.10 (Berkeley) 8/31/92"; 3634203Sbostic #endif /* not lint */ 3712382Sralph 3812382Sralph /* 3915719Sralph * lpc -- line printer control program -- commands: 4012382Sralph */ 4112382Sralph 4255472Sbostic #include <sys/param.h> 4355472Sbostic #include <sys/time.h> 4455472Sbostic #include <sys/stat.h> 4555472Sbostic 4655472Sbostic #include <signal.h> 4755472Sbostic #include <fcntl.h> 4855472Sbostic #include <errno.h> 4955472Sbostic #include <dirent.h> 5055472Sbostic #include <unistd.h> 5155472Sbostic #include <stdlib.h> 5255472Sbostic #include <stdio.h> 5355472Sbostic #include <ctype.h> 5455472Sbostic #include <string.h> 5512382Sralph #include "lp.h" 5655472Sbostic #include "lp.local.h" 5755472Sbostic #include "lpc.h" 5855472Sbostic #include "extern.h" 5937968Sbostic #include "pathnames.h" 6012382Sralph 6155472Sbostic static void abortpr __P((int)); 6255472Sbostic static void cleanpr __P((void)); 63*56121Selan static void disablepr __P((void)); 64*56121Selan static int doarg __P((char *)); 6555472Sbostic static int doselect __P((struct dirent *)); 66*56121Selan static void enablepr __P((void)); 67*56121Selan static void prstat __P((void)); 68*56121Selan static void putmsg __P((int, char **)); 6955472Sbostic static int sortq __P((const void *, const void *)); 70*56121Selan static void startpr __P((int)); 71*56121Selan static void stoppr __P((void)); 72*56121Selan static int touch __P((struct queue *)); 7355472Sbostic static void unlinkf __P((char *)); 74*56121Selan static void upstat __P((char *)); 7555472Sbostic 7612382Sralph /* 7712382Sralph * kill an existing daemon and disable printing. 7812382Sralph */ 7955472Sbostic void 8055472Sbostic doabort(argc, argv) 8155472Sbostic int argc; 8212382Sralph char *argv[]; 8312382Sralph { 8412382Sralph register int c, status; 8512382Sralph register char *cp1, *cp2; 8612382Sralph char prbuf[100]; 8712382Sralph 8812382Sralph if (argc == 1) { 8912382Sralph printf("Usage: abort {all | printer ...}\n"); 9012382Sralph return; 9112382Sralph } 9212382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 9312382Sralph printer = prbuf; 94*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 9512382Sralph cp1 = prbuf; 96*56121Selan cp2 = bp; 9712382Sralph while ((c = *cp2++) && c != '|' && c != ':') 9812382Sralph *cp1++ = c; 9912382Sralph *cp1 = '\0'; 10016755Sralph abortpr(1); 10112382Sralph } 10212382Sralph return; 10312382Sralph } 10412382Sralph while (--argc) { 10512382Sralph printer = *++argv; 106*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 10712514Sralph printf("cannot open printer description file\n"); 10812382Sralph continue; 109*56121Selan } else if (status == -1) { 11012514Sralph printf("unknown printer %s\n", printer); 11112382Sralph continue; 112*56121Selan } else if (status == -3) 113*56121Selan fatal("potential reference loop detected in printcap file"); 11416755Sralph abortpr(1); 11512382Sralph } 11612382Sralph } 11712382Sralph 11855472Sbostic static void 11916755Sralph abortpr(dis) 12055472Sbostic int dis; 12112382Sralph { 12212382Sralph register FILE *fp; 12312382Sralph struct stat stbuf; 12412382Sralph int pid, fd; 12512382Sralph 126*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 12737968Sbostic SD = _PATH_DEFSPOOL; 128*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 12912382Sralph LO = DEFLOCK; 13012382Sralph (void) sprintf(line, "%s/%s", SD, LO); 13112382Sralph printf("%s:\n", printer); 13212382Sralph 13312382Sralph /* 13412382Sralph * Turn on the owner execute bit of the lock file to disable printing. 13512382Sralph */ 13616755Sralph if (dis) { 13716755Sralph if (stat(line, &stbuf) >= 0) { 13816755Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 13916755Sralph printf("\tcannot disable printing\n"); 14038735Stef else { 14138735Stef upstat("printing disabled\n"); 14216755Sralph printf("\tprinting disabled\n"); 14338735Stef } 14416755Sralph } else if (errno == ENOENT) { 14516755Sralph if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 14616755Sralph printf("\tcannot create lock file\n"); 14716755Sralph else { 14816755Sralph (void) close(fd); 14938735Stef upstat("printing disabled\n"); 15016755Sralph printf("\tprinting disabled\n"); 15116755Sralph printf("\tno daemon to abort\n"); 15216755Sralph } 15316755Sralph return; 15416755Sralph } else { 15516755Sralph printf("\tcannot stat lock file\n"); 15616755Sralph return; 15712382Sralph } 15812382Sralph } 15912382Sralph /* 16012382Sralph * Kill the current daemon to stop printing now. 16112382Sralph */ 16212382Sralph if ((fp = fopen(line, "r")) == NULL) { 16312382Sralph printf("\tcannot open lock file\n"); 16412382Sralph return; 16512382Sralph } 16613146Ssam if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 16713168Sralph (void) fclose(fp); /* unlocks as well */ 16812382Sralph printf("\tno daemon to abort\n"); 16912382Sralph return; 17012382Sralph } 17112382Sralph (void) fclose(fp); 17216755Sralph if (kill(pid = atoi(line), SIGTERM) < 0) 17312382Sralph printf("\tWarning: daemon (pid %d) not killed\n", pid); 17412382Sralph else 17512382Sralph printf("\tdaemon (pid %d) killed\n", pid); 17612382Sralph } 17712382Sralph 17812382Sralph /* 17938735Stef * Write a message into the status file. 18038735Stef */ 18155472Sbostic static void 18238735Stef upstat(msg) 18338735Stef char *msg; 18438735Stef { 18538735Stef register int fd; 18638735Stef char statfile[BUFSIZ]; 18738735Stef 188*56121Selan if (cgetstr(bp, "st", &ST) == -1) 18938735Stef ST = DEFSTAT; 19038735Stef (void) sprintf(statfile, "%s/%s", SD, ST); 19138735Stef umask(0); 19238735Stef fd = open(statfile, O_WRONLY|O_CREAT, 0664); 19338735Stef if (fd < 0 || flock(fd, LOCK_EX) < 0) { 19438735Stef printf("\tcannot create status file\n"); 19538735Stef return; 19638735Stef } 19738735Stef (void) ftruncate(fd, 0); 19838735Stef if (msg == (char *)NULL) 19938735Stef (void) write(fd, "\n", 1); 20038735Stef else 20138735Stef (void) write(fd, msg, strlen(msg)); 20238735Stef (void) close(fd); 20338735Stef } 20438735Stef 20538735Stef /* 20612382Sralph * Remove all spool files and temporaries from the spooling area. 20712382Sralph */ 20855472Sbostic void 20912382Sralph clean(argc, argv) 21055472Sbostic int argc; 21112382Sralph char *argv[]; 21212382Sralph { 21312382Sralph register int c, status; 21412382Sralph register char *cp1, *cp2; 21512382Sralph char prbuf[100]; 21612382Sralph 21712382Sralph if (argc == 1) { 21812382Sralph printf("Usage: clean {all | printer ...}\n"); 21912382Sralph return; 22012382Sralph } 22112382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 22212382Sralph printer = prbuf; 223*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 22412382Sralph cp1 = prbuf; 225*56121Selan cp2 = bp; 22612382Sralph while ((c = *cp2++) && c != '|' && c != ':') 22712382Sralph *cp1++ = c; 22812382Sralph *cp1 = '\0'; 22912382Sralph cleanpr(); 23012382Sralph } 23112382Sralph return; 23212382Sralph } 23312382Sralph while (--argc) { 23412382Sralph printer = *++argv; 235*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 23612514Sralph printf("cannot open printer description file\n"); 23712382Sralph continue; 238*56121Selan } else if (status == -1) { 23912514Sralph printf("unknown printer %s\n", printer); 24012382Sralph continue; 241*56121Selan } else if (status == -3) 242*56121Selan fatal("potential reference loop detected in printcap file"); 243*56121Selan 24412382Sralph cleanpr(); 24512382Sralph } 24612382Sralph } 24712382Sralph 24855472Sbostic static int 24955472Sbostic doselect(d) 25055472Sbostic struct dirent *d; 25115719Sralph { 25215719Sralph int c = d->d_name[0]; 25315719Sralph 25415719Sralph if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 25515719Sralph return(1); 25615719Sralph return(0); 25715719Sralph } 25815719Sralph 25915719Sralph /* 26015719Sralph * Comparison routine for scandir. Sort by job number and machine, then 26115719Sralph * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 26215719Sralph */ 26355472Sbostic static int 26455472Sbostic sortq(a, b) 26555472Sbostic const void *a, *b; 26615719Sralph { 26755472Sbostic struct dirent **d1, **d2; 26815719Sralph int c1, c2; 26915719Sralph 27055472Sbostic d1 = (struct dirent **)a; 27155472Sbostic d2 = (struct dirent **)b; 27215719Sralph if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) 27315719Sralph return(c1); 27415719Sralph c1 = (*d1)->d_name[0]; 27515719Sralph c2 = (*d2)->d_name[0]; 27615719Sralph if (c1 == c2) 27715719Sralph return((*d1)->d_name[2] - (*d2)->d_name[2]); 27815719Sralph if (c1 == 'c') 27915719Sralph return(-1); 28015719Sralph if (c1 == 'd' || c2 == 'c') 28115719Sralph return(1); 28215719Sralph return(-1); 28315719Sralph } 28415719Sralph 28515719Sralph /* 28615719Sralph * Remove incomplete jobs from spooling area. 28715719Sralph */ 28855472Sbostic static void 28912382Sralph cleanpr() 29012382Sralph { 29115719Sralph register int i, n; 29215719Sralph register char *cp, *cp1, *lp; 29355472Sbostic struct dirent **queue; 29415719Sralph int nitems; 29512382Sralph 296*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 29737968Sbostic SD = _PATH_DEFSPOOL; 29812382Sralph printf("%s:\n", printer); 29912382Sralph 30015719Sralph for (lp = line, cp = SD; *lp++ = *cp++; ) 30115719Sralph ; 30215719Sralph lp[-1] = '/'; 30315719Sralph 30455472Sbostic nitems = scandir(SD, &queue, doselect, sortq); 30515719Sralph if (nitems < 0) { 30612382Sralph printf("\tcannot examine spool directory\n"); 30712382Sralph return; 30812382Sralph } 30915719Sralph if (nitems == 0) 31015719Sralph return; 31115719Sralph i = 0; 31215719Sralph do { 31315719Sralph cp = queue[i]->d_name; 31415719Sralph if (*cp == 'c') { 31515719Sralph n = 0; 31615719Sralph while (i + 1 < nitems) { 31715719Sralph cp1 = queue[i + 1]->d_name; 31815719Sralph if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 31915719Sralph break; 32015719Sralph i++; 32115719Sralph n++; 32215719Sralph } 32315719Sralph if (n == 0) { 32415719Sralph strcpy(lp, cp); 32515719Sralph unlinkf(line); 32615719Sralph } 32715719Sralph } else { 32815719Sralph /* 32915719Sralph * Must be a df with no cf (otherwise, it would have 33015719Sralph * been skipped above) or a tf file (which can always 33115719Sralph * be removed). 33215719Sralph */ 33315719Sralph strcpy(lp, cp); 33415719Sralph unlinkf(line); 33512382Sralph } 33615719Sralph } while (++i < nitems); 33712382Sralph } 33815719Sralph 33955472Sbostic static void 34015719Sralph unlinkf(name) 34115719Sralph char *name; 34215719Sralph { 34315719Sralph if (unlink(name) < 0) 34415719Sralph printf("\tcannot remove %s\n", name); 34515719Sralph else 34615719Sralph printf("\tremoved %s\n", name); 34715719Sralph } 34812382Sralph 34912382Sralph /* 35012382Sralph * Enable queuing to the printer (allow lpr's). 35112382Sralph */ 35255472Sbostic void 35312382Sralph enable(argc, argv) 35455472Sbostic int argc; 35512382Sralph char *argv[]; 35612382Sralph { 35712382Sralph register int c, status; 35812382Sralph register char *cp1, *cp2; 35912382Sralph char prbuf[100]; 36012382Sralph 36112382Sralph if (argc == 1) { 36212382Sralph printf("Usage: enable {all | printer ...}\n"); 36312382Sralph return; 36412382Sralph } 36512382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 36612382Sralph printer = prbuf; 367*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 36812382Sralph cp1 = prbuf; 369*56121Selan cp2 = bp; 37012382Sralph while ((c = *cp2++) && c != '|' && c != ':') 37112382Sralph *cp1++ = c; 37212382Sralph *cp1 = '\0'; 37312382Sralph enablepr(); 37412382Sralph } 37512382Sralph return; 37612382Sralph } 37712382Sralph while (--argc) { 37812382Sralph printer = *++argv; 379*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 38012514Sralph printf("cannot open printer description file\n"); 38112382Sralph continue; 382*56121Selan } else if (status == -1) { 38312514Sralph printf("unknown printer %s\n", printer); 38412382Sralph continue; 385*56121Selan } else if (status == -3) 386*56121Selan fatal("potential reference loop detected in printcap file"); 387*56121Selan 38812382Sralph enablepr(); 38912382Sralph } 39012382Sralph } 39112382Sralph 39255472Sbostic static void 39312382Sralph enablepr() 39412382Sralph { 39512382Sralph struct stat stbuf; 39612382Sralph 397*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 39837968Sbostic SD = _PATH_DEFSPOOL; 399*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 40012382Sralph LO = DEFLOCK; 40112382Sralph (void) sprintf(line, "%s/%s", SD, LO); 40212382Sralph printf("%s:\n", printer); 40312382Sralph 40412382Sralph /* 40512382Sralph * Turn off the group execute bit of the lock file to enable queuing. 40612382Sralph */ 40712382Sralph if (stat(line, &stbuf) >= 0) { 40812382Sralph if (chmod(line, stbuf.st_mode & 0767) < 0) 40912514Sralph printf("\tcannot enable queuing\n"); 41012382Sralph else 41112382Sralph printf("\tqueuing enabled\n"); 41212382Sralph } 41312382Sralph } 41412382Sralph 41512382Sralph /* 41612382Sralph * Disable queuing. 41712382Sralph */ 41855472Sbostic void 41912382Sralph disable(argc, argv) 42055472Sbostic int argc; 42112382Sralph char *argv[]; 42212382Sralph { 42312382Sralph register int c, status; 42412382Sralph register char *cp1, *cp2; 42512382Sralph char prbuf[100]; 42612382Sralph 42712382Sralph if (argc == 1) { 42812382Sralph printf("Usage: disable {all | printer ...}\n"); 42912382Sralph return; 43012382Sralph } 43112382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 43212382Sralph printer = prbuf; 433*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 43412382Sralph cp1 = prbuf; 435*56121Selan cp2 = bp; 43612382Sralph while ((c = *cp2++) && c != '|' && c != ':') 43712382Sralph *cp1++ = c; 43812382Sralph *cp1 = '\0'; 43912382Sralph disablepr(); 44012382Sralph } 44112382Sralph return; 44212382Sralph } 44312382Sralph while (--argc) { 44412382Sralph printer = *++argv; 445*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 44612514Sralph printf("cannot open printer description file\n"); 44712382Sralph continue; 448*56121Selan } else if (status == -1) { 44912514Sralph printf("unknown printer %s\n", printer); 45012382Sralph continue; 451*56121Selan } else if (status == -3) 452*56121Selan fatal("potential reference loop detected in printcap file"); 453*56121Selan 45412382Sralph disablepr(); 45512382Sralph } 45612382Sralph } 45712382Sralph 45855472Sbostic static void 45912382Sralph disablepr() 46012382Sralph { 46112382Sralph register int fd; 46212382Sralph struct stat stbuf; 46312382Sralph 464*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 46537968Sbostic SD = _PATH_DEFSPOOL; 466*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 46712382Sralph LO = DEFLOCK; 46812382Sralph (void) sprintf(line, "%s/%s", SD, LO); 46912382Sralph printf("%s:\n", printer); 47012382Sralph /* 47112382Sralph * Turn on the group execute bit of the lock file to disable queuing. 47212382Sralph */ 47312382Sralph if (stat(line, &stbuf) >= 0) { 47412382Sralph if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) 47512382Sralph printf("\tcannot disable queuing\n"); 47612382Sralph else 47712382Sralph printf("\tqueuing disabled\n"); 47812382Sralph } else if (errno == ENOENT) { 47913146Ssam if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) 48012382Sralph printf("\tcannot create lock file\n"); 48112382Sralph else { 48212382Sralph (void) close(fd); 48312382Sralph printf("\tqueuing disabled\n"); 48412382Sralph } 48512382Sralph return; 48612382Sralph } else 48712382Sralph printf("\tcannot stat lock file\n"); 48812382Sralph } 48912382Sralph 49012382Sralph /* 49115907Sralph * Disable queuing and printing and put a message into the status file 49215907Sralph * (reason for being down). 49315907Sralph */ 49455472Sbostic void 49515907Sralph down(argc, argv) 49655472Sbostic int argc; 49715907Sralph char *argv[]; 49815907Sralph { 49915907Sralph register int c, status; 50015907Sralph register char *cp1, *cp2; 50115907Sralph char prbuf[100]; 50215907Sralph 50315907Sralph if (argc == 1) { 50416204Sralph printf("Usage: down {all | printer} [message ...]\n"); 50515907Sralph return; 50615907Sralph } 50715907Sralph if (!strcmp(argv[1], "all")) { 50815907Sralph printer = prbuf; 509*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 51015907Sralph cp1 = prbuf; 511*56121Selan cp2 = bp; 51215907Sralph while ((c = *cp2++) && c != '|' && c != ':') 51315907Sralph *cp1++ = c; 51415907Sralph *cp1 = '\0'; 51515907Sralph putmsg(argc - 2, argv + 2); 51615907Sralph } 51715907Sralph return; 51815907Sralph } 51915907Sralph printer = argv[1]; 520*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 52115907Sralph printf("cannot open printer description file\n"); 52215907Sralph return; 523*56121Selan } else if (status == -1) { 52415907Sralph printf("unknown printer %s\n", printer); 52515907Sralph return; 526*56121Selan } else if (status == -3) 527*56121Selan fatal("potential reference loop detected in printcap file"); 528*56121Selan 52915907Sralph putmsg(argc - 2, argv + 2); 53015907Sralph } 53115907Sralph 53255472Sbostic static void 53315907Sralph putmsg(argc, argv) 53455472Sbostic int argc; 53515907Sralph char **argv; 53615907Sralph { 53715907Sralph register int fd; 53815907Sralph register char *cp1, *cp2; 53915907Sralph char buf[1024]; 54015907Sralph struct stat stbuf; 54115907Sralph 542*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 54337968Sbostic SD = _PATH_DEFSPOOL; 544*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 54515907Sralph LO = DEFLOCK; 546*56121Selan if (cgetstr(bp, "st", &ST) == -1) 54715907Sralph ST = DEFSTAT; 54815907Sralph printf("%s:\n", printer); 54915907Sralph /* 55015907Sralph * Turn on the group execute bit of the lock file to disable queuing and 55115907Sralph * turn on the owner execute bit of the lock file to disable printing. 55215907Sralph */ 55315907Sralph (void) sprintf(line, "%s/%s", SD, LO); 55415907Sralph if (stat(line, &stbuf) >= 0) { 55515907Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0) 55615907Sralph printf("\tcannot disable queuing\n"); 55715907Sralph else 55815907Sralph printf("\tprinter and queuing disabled\n"); 55915907Sralph } else if (errno == ENOENT) { 56015907Sralph if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0) 56115907Sralph printf("\tcannot create lock file\n"); 56215907Sralph else { 56315907Sralph (void) close(fd); 56415907Sralph printf("\tprinter and queuing disabled\n"); 56515907Sralph } 56615907Sralph return; 56715907Sralph } else 56815907Sralph printf("\tcannot stat lock file\n"); 56915907Sralph /* 57015907Sralph * Write the message into the status file. 57115907Sralph */ 57215907Sralph (void) sprintf(line, "%s/%s", SD, ST); 57315907Sralph fd = open(line, O_WRONLY|O_CREAT, 0664); 57415907Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 57515907Sralph printf("\tcannot create status file\n"); 57615907Sralph return; 57715907Sralph } 57815907Sralph (void) ftruncate(fd, 0); 57916204Sralph if (argc <= 0) { 58016204Sralph (void) write(fd, "\n", 1); 58116204Sralph (void) close(fd); 58216204Sralph return; 58316204Sralph } 58415907Sralph cp1 = buf; 58515907Sralph while (--argc >= 0) { 58615907Sralph cp2 = *argv++; 58715907Sralph while (*cp1++ = *cp2++) 58815907Sralph ; 58915907Sralph cp1[-1] = ' '; 59015907Sralph } 59115907Sralph cp1[-1] = '\n'; 59215907Sralph *cp1 = '\0'; 59315907Sralph (void) write(fd, buf, strlen(buf)); 59415907Sralph (void) close(fd); 59515907Sralph } 59615907Sralph 59715907Sralph /* 59812382Sralph * Exit lpc 59912382Sralph */ 60055472Sbostic void 60112382Sralph quit(argc, argv) 60255472Sbostic int argc; 60312382Sralph char *argv[]; 60412382Sralph { 60512382Sralph exit(0); 60612382Sralph } 60712382Sralph 60812382Sralph /* 60916755Sralph * Kill and restart the daemon. 61012382Sralph */ 61155472Sbostic void 61212382Sralph restart(argc, argv) 61355472Sbostic int argc; 61412382Sralph char *argv[]; 61512382Sralph { 61612382Sralph register int c, status; 61712382Sralph register char *cp1, *cp2; 61812382Sralph char prbuf[100]; 61912382Sralph 62012382Sralph if (argc == 1) { 62112382Sralph printf("Usage: restart {all | printer ...}\n"); 62212382Sralph return; 62312382Sralph } 62412382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 62512382Sralph printer = prbuf; 626*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 62712382Sralph cp1 = prbuf; 628*56121Selan cp2 = bp; 62912382Sralph while ((c = *cp2++) && c != '|' && c != ':') 63012382Sralph *cp1++ = c; 63112382Sralph *cp1 = '\0'; 63216755Sralph abortpr(0); 63312382Sralph startpr(0); 63412382Sralph } 63512382Sralph return; 63612382Sralph } 63712382Sralph while (--argc) { 63812382Sralph printer = *++argv; 639*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 64012514Sralph printf("cannot open printer description file\n"); 64112382Sralph continue; 642*56121Selan } else if (status == -1) { 64312514Sralph printf("unknown printer %s\n", printer); 64412382Sralph continue; 645*56121Selan } else if (status == -3) 646*56121Selan fatal("potential reference loop detected in printcap file"); 647*56121Selan 64816755Sralph abortpr(0); 64912382Sralph startpr(0); 65012382Sralph } 65112382Sralph } 65212382Sralph 65312382Sralph /* 65412382Sralph * Enable printing on the specified printer and startup the daemon. 65512382Sralph */ 65655472Sbostic void 65712382Sralph start(argc, argv) 65855472Sbostic int argc; 65912382Sralph char *argv[]; 66012382Sralph { 66112382Sralph register int c, status; 66212382Sralph register char *cp1, *cp2; 66312382Sralph char prbuf[100]; 66412382Sralph 66512382Sralph if (argc == 1) { 66612382Sralph printf("Usage: start {all | printer ...}\n"); 66712382Sralph return; 66812382Sralph } 66912382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 67012382Sralph printer = prbuf; 671*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 67212382Sralph cp1 = prbuf; 673*56121Selan cp2 = bp; 67412382Sralph while ((c = *cp2++) && c != '|' && c != ':') 67512382Sralph *cp1++ = c; 67612382Sralph *cp1 = '\0'; 67712382Sralph startpr(1); 67812382Sralph } 67912382Sralph return; 68012382Sralph } 68112382Sralph while (--argc) { 68212382Sralph printer = *++argv; 683*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 68412514Sralph printf("cannot open printer description file\n"); 68512382Sralph continue; 686*56121Selan } else if (status == -1) { 68712514Sralph printf("unknown printer %s\n", printer); 68812382Sralph continue; 689*56121Selan } else if (status == -3) 690*56121Selan fatal("potential reference loop detected in printcap file"); 691*56121Selan 69212382Sralph startpr(1); 69312382Sralph } 69412382Sralph } 69512382Sralph 69655472Sbostic static void 69712382Sralph startpr(enable) 69855472Sbostic int enable; 69912382Sralph { 70012382Sralph struct stat stbuf; 70112382Sralph 702*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 70337968Sbostic SD = _PATH_DEFSPOOL; 704*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 70512382Sralph LO = DEFLOCK; 70612382Sralph (void) sprintf(line, "%s/%s", SD, LO); 70712382Sralph printf("%s:\n", printer); 70812382Sralph 70912382Sralph /* 71012382Sralph * Turn off the owner execute bit of the lock file to enable printing. 71112382Sralph */ 71212382Sralph if (enable && stat(line, &stbuf) >= 0) { 71316771Sralph if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0) 71412382Sralph printf("\tcannot enable printing\n"); 71512382Sralph else 71612382Sralph printf("\tprinting enabled\n"); 71712382Sralph } 71813727Sroot if (!startdaemon(printer)) 71912382Sralph printf("\tcouldn't start daemon\n"); 72012382Sralph else 72112382Sralph printf("\tdaemon started\n"); 72212382Sralph } 72312382Sralph 72412382Sralph /* 72512382Sralph * Print the status of each queue listed or all the queues. 72612382Sralph */ 72755472Sbostic void 72812382Sralph status(argc, argv) 72955472Sbostic int argc; 73012382Sralph char *argv[]; 73112382Sralph { 73212382Sralph register int c, status; 73312382Sralph register char *cp1, *cp2; 73412382Sralph char prbuf[100]; 73512382Sralph 73612382Sralph if (argc == 1) { 73712382Sralph printer = prbuf; 738*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 73912382Sralph cp1 = prbuf; 740*56121Selan cp2 = bp; 74112382Sralph while ((c = *cp2++) && c != '|' && c != ':') 74212382Sralph *cp1++ = c; 74312382Sralph *cp1 = '\0'; 74412382Sralph prstat(); 74512382Sralph } 74612382Sralph return; 74712382Sralph } 74812382Sralph while (--argc) { 74912382Sralph printer = *++argv; 750*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 75112514Sralph printf("cannot open printer description file\n"); 75212382Sralph continue; 753*56121Selan } else if (status == -1) { 75412514Sralph printf("unknown printer %s\n", printer); 75512382Sralph continue; 756*56121Selan } else if (status == -3) 757*56121Selan fatal("potential reference loop detected in printcap file"); 758*56121Selan 75912382Sralph prstat(); 76012382Sralph } 76112382Sralph } 76212382Sralph 76312382Sralph /* 76412382Sralph * Print the status of the printer queue. 76512382Sralph */ 76655472Sbostic static void 76712382Sralph prstat() 76812382Sralph { 76912382Sralph struct stat stbuf; 77012382Sralph register int fd, i; 77155472Sbostic register struct dirent *dp; 77212382Sralph DIR *dirp; 77312382Sralph 774*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 77537968Sbostic SD = _PATH_DEFSPOOL; 776*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 77712382Sralph LO = DEFLOCK; 778*56121Selan if (cgetstr(bp, "st", &ST) == -1) 77912382Sralph ST = DEFSTAT; 78012382Sralph printf("%s:\n", printer); 78112382Sralph (void) sprintf(line, "%s/%s", SD, LO); 78212382Sralph if (stat(line, &stbuf) >= 0) { 78312382Sralph printf("\tqueuing is %s\n", 78412382Sralph (stbuf.st_mode & 010) ? "disabled" : "enabled"); 78512382Sralph printf("\tprinting is %s\n", 78612382Sralph (stbuf.st_mode & 0100) ? "disabled" : "enabled"); 78712382Sralph } else { 78812382Sralph printf("\tqueuing is enabled\n"); 78912382Sralph printf("\tprinting is enabled\n"); 79012382Sralph } 79112382Sralph if ((dirp = opendir(SD)) == NULL) { 79212382Sralph printf("\tcannot examine spool directory\n"); 79312382Sralph return; 79412382Sralph } 79512382Sralph i = 0; 79612382Sralph while ((dp = readdir(dirp)) != NULL) { 79712382Sralph if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 79812382Sralph i++; 79912382Sralph } 80012382Sralph closedir(dirp); 80112382Sralph if (i == 0) 80212382Sralph printf("\tno entries\n"); 80312382Sralph else if (i == 1) 80412382Sralph printf("\t1 entry in spool area\n"); 80512382Sralph else 80612382Sralph printf("\t%d entries in spool area\n", i); 80713146Ssam fd = open(line, O_RDONLY); 80813146Ssam if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 80913168Sralph (void) close(fd); /* unlocks as well */ 81012382Sralph printf("\tno daemon present\n"); 81112382Sralph return; 81212382Sralph } 81312382Sralph (void) close(fd); 81412382Sralph putchar('\t'); 81512382Sralph (void) sprintf(line, "%s/%s", SD, ST); 81613146Ssam fd = open(line, O_RDONLY); 81713146Ssam if (fd >= 0) { 81813146Ssam (void) flock(fd, LOCK_SH); 81912382Sralph while ((i = read(fd, line, sizeof(line))) > 0) 82012382Sralph (void) fwrite(line, 1, i, stdout); 82113168Sralph (void) close(fd); /* unlocks as well */ 82212382Sralph } 82312382Sralph } 82412382Sralph 82512382Sralph /* 82612382Sralph * Stop the specified daemon after completing the current job and disable 82712382Sralph * printing. 82812382Sralph */ 82955472Sbostic void 83012382Sralph stop(argc, argv) 83155472Sbostic int argc; 83212382Sralph char *argv[]; 83312382Sralph { 83412382Sralph register int c, status; 83512382Sralph register char *cp1, *cp2; 83612382Sralph char prbuf[100]; 83712382Sralph 83812382Sralph if (argc == 1) { 83912382Sralph printf("Usage: stop {all | printer ...}\n"); 84012382Sralph return; 84112382Sralph } 84212382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 84312382Sralph printer = prbuf; 844*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 84512382Sralph cp1 = prbuf; 846*56121Selan cp2 = bp; 84712382Sralph while ((c = *cp2++) && c != '|' && c != ':') 84812382Sralph *cp1++ = c; 84912382Sralph *cp1 = '\0'; 85012382Sralph stoppr(); 85112382Sralph } 85212382Sralph return; 85312382Sralph } 85412382Sralph while (--argc) { 85512382Sralph printer = *++argv; 856*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 85712514Sralph printf("cannot open printer description file\n"); 85812382Sralph continue; 859*56121Selan } else if (status == -1) { 86012514Sralph printf("unknown printer %s\n", printer); 86112382Sralph continue; 862*56121Selan } else if (status == -3) 863*56121Selan fatal("potential reference loop detected in printcap file"); 864*56121Selan 86512382Sralph stoppr(); 86612382Sralph } 86712382Sralph } 86812382Sralph 86955472Sbostic static void 87012382Sralph stoppr() 87112382Sralph { 87212382Sralph register int fd; 87312382Sralph struct stat stbuf; 87412382Sralph 875*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 87637968Sbostic SD = _PATH_DEFSPOOL; 877*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 87812382Sralph LO = DEFLOCK; 87912382Sralph (void) sprintf(line, "%s/%s", SD, LO); 88012382Sralph printf("%s:\n", printer); 88112382Sralph 88212382Sralph /* 88312382Sralph * Turn on the owner execute bit of the lock file to disable printing. 88412382Sralph */ 88512382Sralph if (stat(line, &stbuf) >= 0) { 88612382Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 88712382Sralph printf("\tcannot disable printing\n"); 88838735Stef else { 88938735Stef upstat("printing disabled\n"); 89012382Sralph printf("\tprinting disabled\n"); 89138735Stef } 89212382Sralph } else if (errno == ENOENT) { 89313146Ssam if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 89412382Sralph printf("\tcannot create lock file\n"); 89512382Sralph else { 89612382Sralph (void) close(fd); 89738735Stef upstat("printing disabled\n"); 89812382Sralph printf("\tprinting disabled\n"); 89912382Sralph } 90012382Sralph } else 90112382Sralph printf("\tcannot stat lock file\n"); 90212382Sralph } 90313727Sroot 90415719Sralph struct queue **queue; 90515719Sralph int nitems; 90615719Sralph time_t mtime; 90715719Sralph 90813727Sroot /* 90913727Sroot * Put the specified jobs at the top of printer queue. 91013727Sroot */ 91155472Sbostic void 91213727Sroot topq(argc, argv) 91355472Sbostic int argc; 91413727Sroot char *argv[]; 91513727Sroot { 91655472Sbostic register int i; 91713727Sroot struct stat stbuf; 91815719Sralph int status, changed; 91913727Sroot 92015719Sralph if (argc < 3) { 92113727Sroot printf("Usage: topq printer [jobnum ...] [user ...]\n"); 92213727Sroot return; 92313727Sroot } 92413727Sroot 92513727Sroot --argc; 92613727Sroot printer = *++argv; 927*56121Selan status = cgetent(&bp, printcapdb, printer); 928*56121Selan if (status == -2) { 92913727Sroot printf("cannot open printer description file\n"); 93013727Sroot return; 931*56121Selan } else if (status == -1) { 93213727Sroot printf("%s: unknown printer\n", printer); 93313727Sroot return; 934*56121Selan } else if (status == -3) 935*56121Selan fatal("potential reference loop detected in printcap file"); 936*56121Selan 937*56121Selan if (cgetstr(bp, "sd", &SD) == -1) 93837968Sbostic SD = _PATH_DEFSPOOL; 939*56121Selan if (cgetstr(bp, "lo", &LO) == -1) 94013727Sroot LO = DEFLOCK; 94113727Sroot printf("%s:\n", printer); 94213727Sroot 94313727Sroot if (chdir(SD) < 0) { 94413727Sroot printf("\tcannot chdir to %s\n", SD); 94513727Sroot return; 94613727Sroot } 94713727Sroot nitems = getq(&queue); 94815719Sralph if (nitems == 0) 94915719Sralph return; 95015719Sralph changed = 0; 95115719Sralph mtime = queue[0]->q_time; 95215719Sralph for (i = argc; --i; ) { 95315719Sralph if (doarg(argv[i]) == 0) { 95415719Sralph printf("\tjob %s is not in the queue\n", argv[i]); 95513727Sroot continue; 95615719Sralph } else 95714151Sralph changed++; 95813727Sroot } 95915719Sralph for (i = 0; i < nitems; i++) 96015719Sralph free(queue[i]); 96115719Sralph free(queue); 96215719Sralph if (!changed) { 96315719Sralph printf("\tqueue order unchanged\n"); 96415719Sralph return; 96513727Sroot } 96613727Sroot /* 96713727Sroot * Turn on the public execute bit of the lock file to 96813727Sroot * get lpd to rebuild the queue after the current job. 96913727Sroot */ 97014151Sralph if (changed && stat(LO, &stbuf) >= 0) 97114151Sralph (void) chmod(LO, (stbuf.st_mode & 0777) | 01); 97213727Sroot } 97313727Sroot 97415719Sralph /* 97515719Sralph * Reposition the job by changing the modification time of 97615719Sralph * the control file. 97713727Sroot */ 97855472Sbostic static int 97915719Sralph touch(q) 98015719Sralph struct queue *q; 98113727Sroot { 98215719Sralph struct timeval tvp[2]; 98313727Sroot 98415719Sralph tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 98515719Sralph tvp[0].tv_usec = tvp[1].tv_usec = 0; 98615719Sralph return(utimes(q->q_name, tvp)); 98713727Sroot } 98813727Sroot 98913727Sroot /* 99013727Sroot * Checks if specified job name is in the printer's queue. 99113727Sroot * Returns: negative (-1) if argument name is not in the queue. 99213727Sroot */ 99355472Sbostic static int 99415719Sralph doarg(job) 99513727Sroot char *job; 99613727Sroot { 99715719Sralph register struct queue **qq; 99815719Sralph register int jobnum, n; 99915719Sralph register char *cp, *machine; 100015719Sralph int cnt = 0; 100114151Sralph FILE *fp; 100213727Sroot 100315719Sralph /* 100415719Sralph * Look for a job item consisting of system name, colon, number 100515719Sralph * (example: ucbarpa:114) 100615719Sralph */ 100715719Sralph if ((cp = index(job, ':')) != NULL) { 100815719Sralph machine = job; 100915719Sralph *cp++ = '\0'; 101015719Sralph job = cp; 101115719Sralph } else 101215719Sralph machine = NULL; 101315719Sralph 101415719Sralph /* 101515719Sralph * Check for job specified by number (example: 112 or 235ucbarpa). 101615719Sralph */ 101713727Sroot if (isdigit(*job)) { 101813727Sroot jobnum = 0; 101913727Sroot do 102013727Sroot jobnum = jobnum * 10 + (*job++ - '0'); 102113727Sroot while (isdigit(*job)); 102215719Sralph for (qq = queue + nitems; --qq >= queue; ) { 102313727Sroot n = 0; 102415719Sralph for (cp = (*qq)->q_name+3; isdigit(*cp); ) 102514151Sralph n = n * 10 + (*cp++ - '0'); 102615719Sralph if (jobnum != n) 102715719Sralph continue; 102815719Sralph if (*job && strcmp(job, cp) != 0) 102915719Sralph continue; 103015719Sralph if (machine != NULL && strcmp(machine, cp) != 0) 103115719Sralph continue; 103215719Sralph if (touch(*qq) == 0) { 103315719Sralph printf("\tmoved %s\n", (*qq)->q_name); 103415719Sralph cnt++; 103515719Sralph } 103613727Sroot } 103715719Sralph return(cnt); 103815719Sralph } 103915719Sralph /* 104015719Sralph * Process item consisting of owner's name (example: henry). 104115719Sralph */ 104215719Sralph for (qq = queue + nitems; --qq >= queue; ) { 104315719Sralph if ((fp = fopen((*qq)->q_name, "r")) == NULL) 104413727Sroot continue; 104515719Sralph while (getline(fp) > 0) 104615719Sralph if (line[0] == 'P') 104715719Sralph break; 104815719Sralph (void) fclose(fp); 104915719Sralph if (line[0] != 'P' || strcmp(job, line+1) != 0) 105015719Sralph continue; 105115719Sralph if (touch(*qq) == 0) { 105215719Sralph printf("\tmoved %s\n", (*qq)->q_name); 105315719Sralph cnt++; 105413727Sroot } 105513727Sroot } 105615719Sralph return(cnt); 105713727Sroot } 105816755Sralph 105916755Sralph /* 106016755Sralph * Enable everything and start printer (undo `down'). 106116755Sralph */ 106255472Sbostic void 106316755Sralph up(argc, argv) 106455472Sbostic int argc; 106516755Sralph char *argv[]; 106616755Sralph { 106716755Sralph register int c, status; 106816755Sralph register char *cp1, *cp2; 106916755Sralph char prbuf[100]; 107016755Sralph 107116755Sralph if (argc == 1) { 107216755Sralph printf("Usage: up {all | printer ...}\n"); 107316755Sralph return; 107416755Sralph } 107516755Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 107616755Sralph printer = prbuf; 1077*56121Selan while (cgetnext(&bp, printcapdb) > 0) { 107816755Sralph cp1 = prbuf; 1079*56121Selan cp2 = bp; 108016755Sralph while ((c = *cp2++) && c != '|' && c != ':') 108116755Sralph *cp1++ = c; 108216755Sralph *cp1 = '\0'; 108316755Sralph startpr(2); 108416755Sralph } 108516755Sralph return; 108616755Sralph } 108716755Sralph while (--argc) { 108816755Sralph printer = *++argv; 1089*56121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 109016755Sralph printf("cannot open printer description file\n"); 109116755Sralph continue; 1092*56121Selan } else if (status == -1) { 109316755Sralph printf("unknown printer %s\n", printer); 109416755Sralph continue; 1095*56121Selan } else if (status == -3) 1096*56121Selan fatal("potential reference loop detected in printcap file"); 1097*56121Selan 109816755Sralph startpr(2); 109916755Sralph } 110016755Sralph } 1101