122424Sdist /* 256250Selan * Copyright (c) 1983 The Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 556121Selan * 656250Selan * %sccs.include.redist.c% 722424Sdist */ 822424Sdist 912382Sralph #ifndef lint 10*56264Selan static char copyright[] = 1156250Selan "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 1256250Selan All rights reserved.\n"; 1334203Sbostic #endif /* not lint */ 1412382Sralph 1556250Selan #ifndef lint 16*56264Selan static char sccsid[] = "@(#)cmds.c 5.11 (Berkeley) 09/16/92"; 1756250Selan #endif /* not lint */ 1856250Selan 1912382Sralph /* 2015719Sralph * lpc -- line printer control program -- commands: 2112382Sralph */ 2212382Sralph 2355472Sbostic #include <sys/param.h> 2455472Sbostic #include <sys/time.h> 2555472Sbostic #include <sys/stat.h> 2655472Sbostic 2755472Sbostic #include <signal.h> 2855472Sbostic #include <fcntl.h> 2955472Sbostic #include <errno.h> 3055472Sbostic #include <dirent.h> 3155472Sbostic #include <unistd.h> 3255472Sbostic #include <stdlib.h> 3355472Sbostic #include <stdio.h> 3455472Sbostic #include <ctype.h> 3555472Sbostic #include <string.h> 3612382Sralph #include "lp.h" 3755472Sbostic #include "lp.local.h" 3855472Sbostic #include "lpc.h" 3955472Sbostic #include "extern.h" 4037968Sbostic #include "pathnames.h" 4112382Sralph 4255472Sbostic static void abortpr __P((int)); 4355472Sbostic static void cleanpr __P((void)); 4456121Selan static void disablepr __P((void)); 4556121Selan static int doarg __P((char *)); 4655472Sbostic static int doselect __P((struct dirent *)); 4756121Selan static void enablepr __P((void)); 4856121Selan static void prstat __P((void)); 4956121Selan static void putmsg __P((int, char **)); 5055472Sbostic static int sortq __P((const void *, const void *)); 5156121Selan static void startpr __P((int)); 5256121Selan static void stoppr __P((void)); 5356121Selan static int touch __P((struct queue *)); 5455472Sbostic static void unlinkf __P((char *)); 5556121Selan static void upstat __P((char *)); 5655472Sbostic 5712382Sralph /* 5812382Sralph * kill an existing daemon and disable printing. 5912382Sralph */ 6055472Sbostic void 6155472Sbostic doabort(argc, argv) 6255472Sbostic int argc; 6312382Sralph char *argv[]; 6412382Sralph { 6512382Sralph register int c, status; 6612382Sralph register char *cp1, *cp2; 6712382Sralph char prbuf[100]; 6812382Sralph 6912382Sralph if (argc == 1) { 7012382Sralph printf("Usage: abort {all | printer ...}\n"); 7112382Sralph return; 7212382Sralph } 7312382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 7412382Sralph printer = prbuf; 7556121Selan while (cgetnext(&bp, printcapdb) > 0) { 7612382Sralph cp1 = prbuf; 7756121Selan cp2 = bp; 7812382Sralph while ((c = *cp2++) && c != '|' && c != ':') 7912382Sralph *cp1++ = c; 8012382Sralph *cp1 = '\0'; 8116755Sralph abortpr(1); 8212382Sralph } 8312382Sralph return; 8412382Sralph } 8512382Sralph while (--argc) { 8612382Sralph printer = *++argv; 8756121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 8812514Sralph printf("cannot open printer description file\n"); 8912382Sralph continue; 9056121Selan } else if (status == -1) { 9112514Sralph printf("unknown printer %s\n", printer); 9212382Sralph continue; 9356121Selan } else if (status == -3) 9456121Selan fatal("potential reference loop detected in printcap file"); 9516755Sralph abortpr(1); 9612382Sralph } 9712382Sralph } 9812382Sralph 9955472Sbostic static void 10016755Sralph abortpr(dis) 10155472Sbostic int dis; 10212382Sralph { 10312382Sralph register FILE *fp; 10412382Sralph struct stat stbuf; 10512382Sralph int pid, fd; 10612382Sralph 10756121Selan if (cgetstr(bp, "sd", &SD) == -1) 10837968Sbostic SD = _PATH_DEFSPOOL; 10956121Selan if (cgetstr(bp, "lo", &LO) == -1) 11012382Sralph LO = DEFLOCK; 11112382Sralph (void) sprintf(line, "%s/%s", SD, LO); 11212382Sralph printf("%s:\n", printer); 11312382Sralph 11412382Sralph /* 11512382Sralph * Turn on the owner execute bit of the lock file to disable printing. 11612382Sralph */ 11716755Sralph if (dis) { 11816755Sralph if (stat(line, &stbuf) >= 0) { 11916755Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 12016755Sralph printf("\tcannot disable printing\n"); 12138735Stef else { 12238735Stef upstat("printing disabled\n"); 12316755Sralph printf("\tprinting disabled\n"); 12438735Stef } 12516755Sralph } else if (errno == ENOENT) { 12616755Sralph if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 12716755Sralph printf("\tcannot create lock file\n"); 12816755Sralph else { 12916755Sralph (void) close(fd); 13038735Stef upstat("printing disabled\n"); 13116755Sralph printf("\tprinting disabled\n"); 13216755Sralph printf("\tno daemon to abort\n"); 13316755Sralph } 13416755Sralph return; 13516755Sralph } else { 13616755Sralph printf("\tcannot stat lock file\n"); 13716755Sralph return; 13812382Sralph } 13912382Sralph } 14012382Sralph /* 14112382Sralph * Kill the current daemon to stop printing now. 14212382Sralph */ 14312382Sralph if ((fp = fopen(line, "r")) == NULL) { 14412382Sralph printf("\tcannot open lock file\n"); 14512382Sralph return; 14612382Sralph } 14713146Ssam if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 14813168Sralph (void) fclose(fp); /* unlocks as well */ 14912382Sralph printf("\tno daemon to abort\n"); 15012382Sralph return; 15112382Sralph } 15212382Sralph (void) fclose(fp); 15316755Sralph if (kill(pid = atoi(line), SIGTERM) < 0) 15412382Sralph printf("\tWarning: daemon (pid %d) not killed\n", pid); 15512382Sralph else 15612382Sralph printf("\tdaemon (pid %d) killed\n", pid); 15712382Sralph } 15812382Sralph 15912382Sralph /* 16038735Stef * Write a message into the status file. 16138735Stef */ 16255472Sbostic static void 16338735Stef upstat(msg) 16438735Stef char *msg; 16538735Stef { 16638735Stef register int fd; 16738735Stef char statfile[BUFSIZ]; 16838735Stef 16956121Selan if (cgetstr(bp, "st", &ST) == -1) 17038735Stef ST = DEFSTAT; 17138735Stef (void) sprintf(statfile, "%s/%s", SD, ST); 17238735Stef umask(0); 17338735Stef fd = open(statfile, O_WRONLY|O_CREAT, 0664); 17438735Stef if (fd < 0 || flock(fd, LOCK_EX) < 0) { 17538735Stef printf("\tcannot create status file\n"); 17638735Stef return; 17738735Stef } 17838735Stef (void) ftruncate(fd, 0); 17938735Stef if (msg == (char *)NULL) 18038735Stef (void) write(fd, "\n", 1); 18138735Stef else 18238735Stef (void) write(fd, msg, strlen(msg)); 18338735Stef (void) close(fd); 18438735Stef } 18538735Stef 18638735Stef /* 18712382Sralph * Remove all spool files and temporaries from the spooling area. 18812382Sralph */ 18955472Sbostic void 19012382Sralph clean(argc, argv) 19155472Sbostic int argc; 19212382Sralph char *argv[]; 19312382Sralph { 19412382Sralph register int c, status; 19512382Sralph register char *cp1, *cp2; 19612382Sralph char prbuf[100]; 19712382Sralph 19812382Sralph if (argc == 1) { 19912382Sralph printf("Usage: clean {all | printer ...}\n"); 20012382Sralph return; 20112382Sralph } 20212382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 20312382Sralph printer = prbuf; 20456121Selan while (cgetnext(&bp, printcapdb) > 0) { 20512382Sralph cp1 = prbuf; 20656121Selan cp2 = bp; 20712382Sralph while ((c = *cp2++) && c != '|' && c != ':') 20812382Sralph *cp1++ = c; 20912382Sralph *cp1 = '\0'; 21012382Sralph cleanpr(); 21112382Sralph } 21212382Sralph return; 21312382Sralph } 21412382Sralph while (--argc) { 21512382Sralph printer = *++argv; 21656121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 21712514Sralph printf("cannot open printer description file\n"); 21812382Sralph continue; 21956121Selan } else if (status == -1) { 22012514Sralph printf("unknown printer %s\n", printer); 22112382Sralph continue; 22256121Selan } else if (status == -3) 22356121Selan fatal("potential reference loop detected in printcap file"); 22456121Selan 22512382Sralph cleanpr(); 22612382Sralph } 22712382Sralph } 22812382Sralph 22955472Sbostic static int 23055472Sbostic doselect(d) 23155472Sbostic struct dirent *d; 23215719Sralph { 23315719Sralph int c = d->d_name[0]; 23415719Sralph 23515719Sralph if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 23615719Sralph return(1); 23715719Sralph return(0); 23815719Sralph } 23915719Sralph 24015719Sralph /* 24115719Sralph * Comparison routine for scandir. Sort by job number and machine, then 24215719Sralph * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 24315719Sralph */ 24455472Sbostic static int 24555472Sbostic sortq(a, b) 24655472Sbostic const void *a, *b; 24715719Sralph { 24855472Sbostic struct dirent **d1, **d2; 24915719Sralph int c1, c2; 25015719Sralph 25155472Sbostic d1 = (struct dirent **)a; 25255472Sbostic d2 = (struct dirent **)b; 25315719Sralph if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) 25415719Sralph return(c1); 25515719Sralph c1 = (*d1)->d_name[0]; 25615719Sralph c2 = (*d2)->d_name[0]; 25715719Sralph if (c1 == c2) 25815719Sralph return((*d1)->d_name[2] - (*d2)->d_name[2]); 25915719Sralph if (c1 == 'c') 26015719Sralph return(-1); 26115719Sralph if (c1 == 'd' || c2 == 'c') 26215719Sralph return(1); 26315719Sralph return(-1); 26415719Sralph } 26515719Sralph 26615719Sralph /* 26715719Sralph * Remove incomplete jobs from spooling area. 26815719Sralph */ 26955472Sbostic static void 27012382Sralph cleanpr() 27112382Sralph { 27215719Sralph register int i, n; 27315719Sralph register char *cp, *cp1, *lp; 27455472Sbostic struct dirent **queue; 27515719Sralph int nitems; 27612382Sralph 27756121Selan if (cgetstr(bp, "sd", &SD) == -1) 27837968Sbostic SD = _PATH_DEFSPOOL; 27912382Sralph printf("%s:\n", printer); 28012382Sralph 28115719Sralph for (lp = line, cp = SD; *lp++ = *cp++; ) 28215719Sralph ; 28315719Sralph lp[-1] = '/'; 28415719Sralph 28555472Sbostic nitems = scandir(SD, &queue, doselect, sortq); 28615719Sralph if (nitems < 0) { 28712382Sralph printf("\tcannot examine spool directory\n"); 28812382Sralph return; 28912382Sralph } 29015719Sralph if (nitems == 0) 29115719Sralph return; 29215719Sralph i = 0; 29315719Sralph do { 29415719Sralph cp = queue[i]->d_name; 29515719Sralph if (*cp == 'c') { 29615719Sralph n = 0; 29715719Sralph while (i + 1 < nitems) { 29815719Sralph cp1 = queue[i + 1]->d_name; 29915719Sralph if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 30015719Sralph break; 30115719Sralph i++; 30215719Sralph n++; 30315719Sralph } 30415719Sralph if (n == 0) { 30515719Sralph strcpy(lp, cp); 30615719Sralph unlinkf(line); 30715719Sralph } 30815719Sralph } else { 30915719Sralph /* 31015719Sralph * Must be a df with no cf (otherwise, it would have 31115719Sralph * been skipped above) or a tf file (which can always 31215719Sralph * be removed). 31315719Sralph */ 31415719Sralph strcpy(lp, cp); 31515719Sralph unlinkf(line); 31612382Sralph } 31715719Sralph } while (++i < nitems); 31812382Sralph } 31915719Sralph 32055472Sbostic static void 32115719Sralph unlinkf(name) 32215719Sralph char *name; 32315719Sralph { 32415719Sralph if (unlink(name) < 0) 32515719Sralph printf("\tcannot remove %s\n", name); 32615719Sralph else 32715719Sralph printf("\tremoved %s\n", name); 32815719Sralph } 32912382Sralph 33012382Sralph /* 33112382Sralph * Enable queuing to the printer (allow lpr's). 33212382Sralph */ 33355472Sbostic void 33412382Sralph enable(argc, argv) 33555472Sbostic int argc; 33612382Sralph char *argv[]; 33712382Sralph { 33812382Sralph register int c, status; 33912382Sralph register char *cp1, *cp2; 34012382Sralph char prbuf[100]; 34112382Sralph 34212382Sralph if (argc == 1) { 34312382Sralph printf("Usage: enable {all | printer ...}\n"); 34412382Sralph return; 34512382Sralph } 34612382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 34712382Sralph printer = prbuf; 34856121Selan while (cgetnext(&bp, printcapdb) > 0) { 34912382Sralph cp1 = prbuf; 35056121Selan cp2 = bp; 35112382Sralph while ((c = *cp2++) && c != '|' && c != ':') 35212382Sralph *cp1++ = c; 35312382Sralph *cp1 = '\0'; 35412382Sralph enablepr(); 35512382Sralph } 35612382Sralph return; 35712382Sralph } 35812382Sralph while (--argc) { 35912382Sralph printer = *++argv; 36056121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 36112514Sralph printf("cannot open printer description file\n"); 36212382Sralph continue; 36356121Selan } else if (status == -1) { 36412514Sralph printf("unknown printer %s\n", printer); 36512382Sralph continue; 36656121Selan } else if (status == -3) 36756121Selan fatal("potential reference loop detected in printcap file"); 36856121Selan 36912382Sralph enablepr(); 37012382Sralph } 37112382Sralph } 37212382Sralph 37355472Sbostic static void 37412382Sralph enablepr() 37512382Sralph { 37612382Sralph struct stat stbuf; 37712382Sralph 37856121Selan if (cgetstr(bp, "sd", &SD) == -1) 37937968Sbostic SD = _PATH_DEFSPOOL; 38056121Selan if (cgetstr(bp, "lo", &LO) == -1) 38112382Sralph LO = DEFLOCK; 38212382Sralph (void) sprintf(line, "%s/%s", SD, LO); 38312382Sralph printf("%s:\n", printer); 38412382Sralph 38512382Sralph /* 38612382Sralph * Turn off the group execute bit of the lock file to enable queuing. 38712382Sralph */ 38812382Sralph if (stat(line, &stbuf) >= 0) { 38912382Sralph if (chmod(line, stbuf.st_mode & 0767) < 0) 39012514Sralph printf("\tcannot enable queuing\n"); 39112382Sralph else 39212382Sralph printf("\tqueuing enabled\n"); 39312382Sralph } 39412382Sralph } 39512382Sralph 39612382Sralph /* 39712382Sralph * Disable queuing. 39812382Sralph */ 39955472Sbostic void 40012382Sralph disable(argc, argv) 40155472Sbostic int argc; 40212382Sralph char *argv[]; 40312382Sralph { 40412382Sralph register int c, status; 40512382Sralph register char *cp1, *cp2; 40612382Sralph char prbuf[100]; 40712382Sralph 40812382Sralph if (argc == 1) { 40912382Sralph printf("Usage: disable {all | printer ...}\n"); 41012382Sralph return; 41112382Sralph } 41212382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 41312382Sralph printer = prbuf; 41456121Selan while (cgetnext(&bp, printcapdb) > 0) { 41512382Sralph cp1 = prbuf; 41656121Selan cp2 = bp; 41712382Sralph while ((c = *cp2++) && c != '|' && c != ':') 41812382Sralph *cp1++ = c; 41912382Sralph *cp1 = '\0'; 42012382Sralph disablepr(); 42112382Sralph } 42212382Sralph return; 42312382Sralph } 42412382Sralph while (--argc) { 42512382Sralph printer = *++argv; 42656121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 42712514Sralph printf("cannot open printer description file\n"); 42812382Sralph continue; 42956121Selan } else if (status == -1) { 43012514Sralph printf("unknown printer %s\n", printer); 43112382Sralph continue; 43256121Selan } else if (status == -3) 43356121Selan fatal("potential reference loop detected in printcap file"); 43456121Selan 43512382Sralph disablepr(); 43612382Sralph } 43712382Sralph } 43812382Sralph 43955472Sbostic static void 44012382Sralph disablepr() 44112382Sralph { 44212382Sralph register int fd; 44312382Sralph struct stat stbuf; 44412382Sralph 44556121Selan if (cgetstr(bp, "sd", &SD) == -1) 44637968Sbostic SD = _PATH_DEFSPOOL; 44756121Selan if (cgetstr(bp, "lo", &LO) == -1) 44812382Sralph LO = DEFLOCK; 44912382Sralph (void) sprintf(line, "%s/%s", SD, LO); 45012382Sralph printf("%s:\n", printer); 45112382Sralph /* 45212382Sralph * Turn on the group execute bit of the lock file to disable queuing. 45312382Sralph */ 45412382Sralph if (stat(line, &stbuf) >= 0) { 45512382Sralph if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) 45612382Sralph printf("\tcannot disable queuing\n"); 45712382Sralph else 45812382Sralph printf("\tqueuing disabled\n"); 45912382Sralph } else if (errno == ENOENT) { 46013146Ssam if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) 46112382Sralph printf("\tcannot create lock file\n"); 46212382Sralph else { 46312382Sralph (void) close(fd); 46412382Sralph printf("\tqueuing disabled\n"); 46512382Sralph } 46612382Sralph return; 46712382Sralph } else 46812382Sralph printf("\tcannot stat lock file\n"); 46912382Sralph } 47012382Sralph 47112382Sralph /* 47215907Sralph * Disable queuing and printing and put a message into the status file 47315907Sralph * (reason for being down). 47415907Sralph */ 47555472Sbostic void 47615907Sralph down(argc, argv) 47755472Sbostic int argc; 47815907Sralph char *argv[]; 47915907Sralph { 48015907Sralph register int c, status; 48115907Sralph register char *cp1, *cp2; 48215907Sralph char prbuf[100]; 48315907Sralph 48415907Sralph if (argc == 1) { 48516204Sralph printf("Usage: down {all | printer} [message ...]\n"); 48615907Sralph return; 48715907Sralph } 48815907Sralph if (!strcmp(argv[1], "all")) { 48915907Sralph printer = prbuf; 49056121Selan while (cgetnext(&bp, printcapdb) > 0) { 49115907Sralph cp1 = prbuf; 49256121Selan cp2 = bp; 49315907Sralph while ((c = *cp2++) && c != '|' && c != ':') 49415907Sralph *cp1++ = c; 49515907Sralph *cp1 = '\0'; 49615907Sralph putmsg(argc - 2, argv + 2); 49715907Sralph } 49815907Sralph return; 49915907Sralph } 50015907Sralph printer = argv[1]; 50156121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 50215907Sralph printf("cannot open printer description file\n"); 50315907Sralph return; 50456121Selan } else if (status == -1) { 50515907Sralph printf("unknown printer %s\n", printer); 50615907Sralph return; 50756121Selan } else if (status == -3) 50856121Selan fatal("potential reference loop detected in printcap file"); 50956121Selan 51015907Sralph putmsg(argc - 2, argv + 2); 51115907Sralph } 51215907Sralph 51355472Sbostic static void 51415907Sralph putmsg(argc, argv) 51555472Sbostic int argc; 51615907Sralph char **argv; 51715907Sralph { 51815907Sralph register int fd; 51915907Sralph register char *cp1, *cp2; 52015907Sralph char buf[1024]; 52115907Sralph struct stat stbuf; 52215907Sralph 52356121Selan if (cgetstr(bp, "sd", &SD) == -1) 52437968Sbostic SD = _PATH_DEFSPOOL; 52556121Selan if (cgetstr(bp, "lo", &LO) == -1) 52615907Sralph LO = DEFLOCK; 52756121Selan if (cgetstr(bp, "st", &ST) == -1) 52815907Sralph ST = DEFSTAT; 52915907Sralph printf("%s:\n", printer); 53015907Sralph /* 53115907Sralph * Turn on the group execute bit of the lock file to disable queuing and 53215907Sralph * turn on the owner execute bit of the lock file to disable printing. 53315907Sralph */ 53415907Sralph (void) sprintf(line, "%s/%s", SD, LO); 53515907Sralph if (stat(line, &stbuf) >= 0) { 53615907Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0) 53715907Sralph printf("\tcannot disable queuing\n"); 53815907Sralph else 53915907Sralph printf("\tprinter and queuing disabled\n"); 54015907Sralph } else if (errno == ENOENT) { 54115907Sralph if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0) 54215907Sralph printf("\tcannot create lock file\n"); 54315907Sralph else { 54415907Sralph (void) close(fd); 54515907Sralph printf("\tprinter and queuing disabled\n"); 54615907Sralph } 54715907Sralph return; 54815907Sralph } else 54915907Sralph printf("\tcannot stat lock file\n"); 55015907Sralph /* 55115907Sralph * Write the message into the status file. 55215907Sralph */ 55315907Sralph (void) sprintf(line, "%s/%s", SD, ST); 55415907Sralph fd = open(line, O_WRONLY|O_CREAT, 0664); 55515907Sralph if (fd < 0 || flock(fd, LOCK_EX) < 0) { 55615907Sralph printf("\tcannot create status file\n"); 55715907Sralph return; 55815907Sralph } 55915907Sralph (void) ftruncate(fd, 0); 56016204Sralph if (argc <= 0) { 56116204Sralph (void) write(fd, "\n", 1); 56216204Sralph (void) close(fd); 56316204Sralph return; 56416204Sralph } 56515907Sralph cp1 = buf; 56615907Sralph while (--argc >= 0) { 56715907Sralph cp2 = *argv++; 56815907Sralph while (*cp1++ = *cp2++) 56915907Sralph ; 57015907Sralph cp1[-1] = ' '; 57115907Sralph } 57215907Sralph cp1[-1] = '\n'; 57315907Sralph *cp1 = '\0'; 57415907Sralph (void) write(fd, buf, strlen(buf)); 57515907Sralph (void) close(fd); 57615907Sralph } 57715907Sralph 57815907Sralph /* 57912382Sralph * Exit lpc 58012382Sralph */ 58155472Sbostic void 58212382Sralph quit(argc, argv) 58355472Sbostic int argc; 58412382Sralph char *argv[]; 58512382Sralph { 58612382Sralph exit(0); 58712382Sralph } 58812382Sralph 58912382Sralph /* 59016755Sralph * Kill and restart the daemon. 59112382Sralph */ 59255472Sbostic void 59312382Sralph restart(argc, argv) 59455472Sbostic int argc; 59512382Sralph char *argv[]; 59612382Sralph { 59712382Sralph register int c, status; 59812382Sralph register char *cp1, *cp2; 59912382Sralph char prbuf[100]; 60012382Sralph 60112382Sralph if (argc == 1) { 60212382Sralph printf("Usage: restart {all | printer ...}\n"); 60312382Sralph return; 60412382Sralph } 60512382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 60612382Sralph printer = prbuf; 60756121Selan while (cgetnext(&bp, printcapdb) > 0) { 60812382Sralph cp1 = prbuf; 60956121Selan cp2 = bp; 61012382Sralph while ((c = *cp2++) && c != '|' && c != ':') 61112382Sralph *cp1++ = c; 61212382Sralph *cp1 = '\0'; 61316755Sralph abortpr(0); 61412382Sralph startpr(0); 61512382Sralph } 61612382Sralph return; 61712382Sralph } 61812382Sralph while (--argc) { 61912382Sralph printer = *++argv; 62056121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 62112514Sralph printf("cannot open printer description file\n"); 62212382Sralph continue; 62356121Selan } else if (status == -1) { 62412514Sralph printf("unknown printer %s\n", printer); 62512382Sralph continue; 62656121Selan } else if (status == -3) 62756121Selan fatal("potential reference loop detected in printcap file"); 62856121Selan 62916755Sralph abortpr(0); 63012382Sralph startpr(0); 63112382Sralph } 63212382Sralph } 63312382Sralph 63412382Sralph /* 63512382Sralph * Enable printing on the specified printer and startup the daemon. 63612382Sralph */ 63755472Sbostic void 63812382Sralph start(argc, argv) 63955472Sbostic int argc; 64012382Sralph char *argv[]; 64112382Sralph { 64212382Sralph register int c, status; 64312382Sralph register char *cp1, *cp2; 64412382Sralph char prbuf[100]; 64512382Sralph 64612382Sralph if (argc == 1) { 64712382Sralph printf("Usage: start {all | printer ...}\n"); 64812382Sralph return; 64912382Sralph } 65012382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 65112382Sralph printer = prbuf; 65256121Selan while (cgetnext(&bp, printcapdb) > 0) { 65312382Sralph cp1 = prbuf; 65456121Selan cp2 = bp; 65512382Sralph while ((c = *cp2++) && c != '|' && c != ':') 65612382Sralph *cp1++ = c; 65712382Sralph *cp1 = '\0'; 65812382Sralph startpr(1); 65912382Sralph } 66012382Sralph return; 66112382Sralph } 66212382Sralph while (--argc) { 66312382Sralph printer = *++argv; 66456121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 66512514Sralph printf("cannot open printer description file\n"); 66612382Sralph continue; 66756121Selan } else if (status == -1) { 66812514Sralph printf("unknown printer %s\n", printer); 66912382Sralph continue; 67056121Selan } else if (status == -3) 67156121Selan fatal("potential reference loop detected in printcap file"); 67256121Selan 67312382Sralph startpr(1); 67412382Sralph } 67512382Sralph } 67612382Sralph 67755472Sbostic static void 67812382Sralph startpr(enable) 67955472Sbostic int enable; 68012382Sralph { 68112382Sralph struct stat stbuf; 68212382Sralph 68356121Selan if (cgetstr(bp, "sd", &SD) == -1) 68437968Sbostic SD = _PATH_DEFSPOOL; 68556121Selan if (cgetstr(bp, "lo", &LO) == -1) 68612382Sralph LO = DEFLOCK; 68712382Sralph (void) sprintf(line, "%s/%s", SD, LO); 68812382Sralph printf("%s:\n", printer); 68912382Sralph 69012382Sralph /* 69112382Sralph * Turn off the owner execute bit of the lock file to enable printing. 69212382Sralph */ 69312382Sralph if (enable && stat(line, &stbuf) >= 0) { 69416771Sralph if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0) 69512382Sralph printf("\tcannot enable printing\n"); 69612382Sralph else 69712382Sralph printf("\tprinting enabled\n"); 69812382Sralph } 69913727Sroot if (!startdaemon(printer)) 70012382Sralph printf("\tcouldn't start daemon\n"); 70112382Sralph else 70212382Sralph printf("\tdaemon started\n"); 70312382Sralph } 70412382Sralph 70512382Sralph /* 70612382Sralph * Print the status of each queue listed or all the queues. 70712382Sralph */ 70855472Sbostic void 70912382Sralph status(argc, argv) 71055472Sbostic int argc; 71112382Sralph char *argv[]; 71212382Sralph { 71312382Sralph register int c, status; 71412382Sralph register char *cp1, *cp2; 71512382Sralph char prbuf[100]; 71612382Sralph 71712382Sralph if (argc == 1) { 71812382Sralph printer = prbuf; 71956121Selan while (cgetnext(&bp, printcapdb) > 0) { 72012382Sralph cp1 = prbuf; 72156121Selan cp2 = bp; 72212382Sralph while ((c = *cp2++) && c != '|' && c != ':') 72312382Sralph *cp1++ = c; 72412382Sralph *cp1 = '\0'; 72512382Sralph prstat(); 72612382Sralph } 72712382Sralph return; 72812382Sralph } 72912382Sralph while (--argc) { 73012382Sralph printer = *++argv; 73156121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 73212514Sralph printf("cannot open printer description file\n"); 73312382Sralph continue; 73456121Selan } else if (status == -1) { 73512514Sralph printf("unknown printer %s\n", printer); 73612382Sralph continue; 73756121Selan } else if (status == -3) 73856121Selan fatal("potential reference loop detected in printcap file"); 73956121Selan 74012382Sralph prstat(); 74112382Sralph } 74212382Sralph } 74312382Sralph 74412382Sralph /* 74512382Sralph * Print the status of the printer queue. 74612382Sralph */ 74755472Sbostic static void 74812382Sralph prstat() 74912382Sralph { 75012382Sralph struct stat stbuf; 75112382Sralph register int fd, i; 75255472Sbostic register struct dirent *dp; 75312382Sralph DIR *dirp; 75412382Sralph 75556121Selan if (cgetstr(bp, "sd", &SD) == -1) 75637968Sbostic SD = _PATH_DEFSPOOL; 75756121Selan if (cgetstr(bp, "lo", &LO) == -1) 75812382Sralph LO = DEFLOCK; 75956121Selan if (cgetstr(bp, "st", &ST) == -1) 76012382Sralph ST = DEFSTAT; 76112382Sralph printf("%s:\n", printer); 76212382Sralph (void) sprintf(line, "%s/%s", SD, LO); 76312382Sralph if (stat(line, &stbuf) >= 0) { 76412382Sralph printf("\tqueuing is %s\n", 76512382Sralph (stbuf.st_mode & 010) ? "disabled" : "enabled"); 76612382Sralph printf("\tprinting is %s\n", 76712382Sralph (stbuf.st_mode & 0100) ? "disabled" : "enabled"); 76812382Sralph } else { 76912382Sralph printf("\tqueuing is enabled\n"); 77012382Sralph printf("\tprinting is enabled\n"); 77112382Sralph } 77212382Sralph if ((dirp = opendir(SD)) == NULL) { 77312382Sralph printf("\tcannot examine spool directory\n"); 77412382Sralph return; 77512382Sralph } 77612382Sralph i = 0; 77712382Sralph while ((dp = readdir(dirp)) != NULL) { 77812382Sralph if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 77912382Sralph i++; 78012382Sralph } 78112382Sralph closedir(dirp); 78212382Sralph if (i == 0) 78312382Sralph printf("\tno entries\n"); 78412382Sralph else if (i == 1) 78512382Sralph printf("\t1 entry in spool area\n"); 78612382Sralph else 78712382Sralph printf("\t%d entries in spool area\n", i); 78813146Ssam fd = open(line, O_RDONLY); 78913146Ssam if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 79013168Sralph (void) close(fd); /* unlocks as well */ 79112382Sralph printf("\tno daemon present\n"); 79212382Sralph return; 79312382Sralph } 79412382Sralph (void) close(fd); 79512382Sralph putchar('\t'); 79612382Sralph (void) sprintf(line, "%s/%s", SD, ST); 79713146Ssam fd = open(line, O_RDONLY); 79813146Ssam if (fd >= 0) { 79913146Ssam (void) flock(fd, LOCK_SH); 80012382Sralph while ((i = read(fd, line, sizeof(line))) > 0) 80112382Sralph (void) fwrite(line, 1, i, stdout); 80213168Sralph (void) close(fd); /* unlocks as well */ 80312382Sralph } 80412382Sralph } 80512382Sralph 80612382Sralph /* 80712382Sralph * Stop the specified daemon after completing the current job and disable 80812382Sralph * printing. 80912382Sralph */ 81055472Sbostic void 81112382Sralph stop(argc, argv) 81255472Sbostic int argc; 81312382Sralph char *argv[]; 81412382Sralph { 81512382Sralph register int c, status; 81612382Sralph register char *cp1, *cp2; 81712382Sralph char prbuf[100]; 81812382Sralph 81912382Sralph if (argc == 1) { 82012382Sralph printf("Usage: stop {all | printer ...}\n"); 82112382Sralph return; 82212382Sralph } 82312382Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 82412382Sralph printer = prbuf; 82556121Selan while (cgetnext(&bp, printcapdb) > 0) { 82612382Sralph cp1 = prbuf; 82756121Selan cp2 = bp; 82812382Sralph while ((c = *cp2++) && c != '|' && c != ':') 82912382Sralph *cp1++ = c; 83012382Sralph *cp1 = '\0'; 83112382Sralph stoppr(); 83212382Sralph } 83312382Sralph return; 83412382Sralph } 83512382Sralph while (--argc) { 83612382Sralph printer = *++argv; 83756121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 83812514Sralph printf("cannot open printer description file\n"); 83912382Sralph continue; 84056121Selan } else if (status == -1) { 84112514Sralph printf("unknown printer %s\n", printer); 84212382Sralph continue; 84356121Selan } else if (status == -3) 84456121Selan fatal("potential reference loop detected in printcap file"); 84556121Selan 84612382Sralph stoppr(); 84712382Sralph } 84812382Sralph } 84912382Sralph 85055472Sbostic static void 85112382Sralph stoppr() 85212382Sralph { 85312382Sralph register int fd; 85412382Sralph struct stat stbuf; 85512382Sralph 85656121Selan if (cgetstr(bp, "sd", &SD) == -1) 85737968Sbostic SD = _PATH_DEFSPOOL; 85856121Selan if (cgetstr(bp, "lo", &LO) == -1) 85912382Sralph LO = DEFLOCK; 86012382Sralph (void) sprintf(line, "%s/%s", SD, LO); 86112382Sralph printf("%s:\n", printer); 86212382Sralph 86312382Sralph /* 86412382Sralph * Turn on the owner execute bit of the lock file to disable printing. 86512382Sralph */ 86612382Sralph if (stat(line, &stbuf) >= 0) { 86712382Sralph if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 86812382Sralph printf("\tcannot disable printing\n"); 86938735Stef else { 87038735Stef upstat("printing disabled\n"); 87112382Sralph printf("\tprinting disabled\n"); 87238735Stef } 87312382Sralph } else if (errno == ENOENT) { 87413146Ssam if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 87512382Sralph printf("\tcannot create lock file\n"); 87612382Sralph else { 87712382Sralph (void) close(fd); 87838735Stef upstat("printing disabled\n"); 87912382Sralph printf("\tprinting disabled\n"); 88012382Sralph } 88112382Sralph } else 88212382Sralph printf("\tcannot stat lock file\n"); 88312382Sralph } 88413727Sroot 88515719Sralph struct queue **queue; 88615719Sralph int nitems; 88715719Sralph time_t mtime; 88815719Sralph 88913727Sroot /* 89013727Sroot * Put the specified jobs at the top of printer queue. 89113727Sroot */ 89255472Sbostic void 89313727Sroot topq(argc, argv) 89455472Sbostic int argc; 89513727Sroot char *argv[]; 89613727Sroot { 89755472Sbostic register int i; 89813727Sroot struct stat stbuf; 89915719Sralph int status, changed; 90013727Sroot 90115719Sralph if (argc < 3) { 90213727Sroot printf("Usage: topq printer [jobnum ...] [user ...]\n"); 90313727Sroot return; 90413727Sroot } 90513727Sroot 90613727Sroot --argc; 90713727Sroot printer = *++argv; 90856121Selan status = cgetent(&bp, printcapdb, printer); 90956121Selan if (status == -2) { 91013727Sroot printf("cannot open printer description file\n"); 91113727Sroot return; 91256121Selan } else if (status == -1) { 91313727Sroot printf("%s: unknown printer\n", printer); 91413727Sroot return; 91556121Selan } else if (status == -3) 91656121Selan fatal("potential reference loop detected in printcap file"); 91756121Selan 91856121Selan if (cgetstr(bp, "sd", &SD) == -1) 91937968Sbostic SD = _PATH_DEFSPOOL; 92056121Selan if (cgetstr(bp, "lo", &LO) == -1) 92113727Sroot LO = DEFLOCK; 92213727Sroot printf("%s:\n", printer); 92313727Sroot 92413727Sroot if (chdir(SD) < 0) { 92513727Sroot printf("\tcannot chdir to %s\n", SD); 92613727Sroot return; 92713727Sroot } 92813727Sroot nitems = getq(&queue); 92915719Sralph if (nitems == 0) 93015719Sralph return; 93115719Sralph changed = 0; 93215719Sralph mtime = queue[0]->q_time; 93315719Sralph for (i = argc; --i; ) { 93415719Sralph if (doarg(argv[i]) == 0) { 93515719Sralph printf("\tjob %s is not in the queue\n", argv[i]); 93613727Sroot continue; 93715719Sralph } else 93814151Sralph changed++; 93913727Sroot } 94015719Sralph for (i = 0; i < nitems; i++) 94115719Sralph free(queue[i]); 94215719Sralph free(queue); 94315719Sralph if (!changed) { 94415719Sralph printf("\tqueue order unchanged\n"); 94515719Sralph return; 94613727Sroot } 94713727Sroot /* 94813727Sroot * Turn on the public execute bit of the lock file to 94913727Sroot * get lpd to rebuild the queue after the current job. 95013727Sroot */ 95114151Sralph if (changed && stat(LO, &stbuf) >= 0) 95214151Sralph (void) chmod(LO, (stbuf.st_mode & 0777) | 01); 95313727Sroot } 95413727Sroot 95515719Sralph /* 95615719Sralph * Reposition the job by changing the modification time of 95715719Sralph * the control file. 95813727Sroot */ 95955472Sbostic static int 96015719Sralph touch(q) 96115719Sralph struct queue *q; 96213727Sroot { 96315719Sralph struct timeval tvp[2]; 96413727Sroot 96515719Sralph tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 96615719Sralph tvp[0].tv_usec = tvp[1].tv_usec = 0; 96715719Sralph return(utimes(q->q_name, tvp)); 96813727Sroot } 96913727Sroot 97013727Sroot /* 97113727Sroot * Checks if specified job name is in the printer's queue. 97213727Sroot * Returns: negative (-1) if argument name is not in the queue. 97313727Sroot */ 97455472Sbostic static int 97515719Sralph doarg(job) 97613727Sroot char *job; 97713727Sroot { 97815719Sralph register struct queue **qq; 97915719Sralph register int jobnum, n; 98015719Sralph register char *cp, *machine; 98115719Sralph int cnt = 0; 98214151Sralph FILE *fp; 98313727Sroot 98415719Sralph /* 98515719Sralph * Look for a job item consisting of system name, colon, number 98615719Sralph * (example: ucbarpa:114) 98715719Sralph */ 98815719Sralph if ((cp = index(job, ':')) != NULL) { 98915719Sralph machine = job; 99015719Sralph *cp++ = '\0'; 99115719Sralph job = cp; 99215719Sralph } else 99315719Sralph machine = NULL; 99415719Sralph 99515719Sralph /* 99615719Sralph * Check for job specified by number (example: 112 or 235ucbarpa). 99715719Sralph */ 99813727Sroot if (isdigit(*job)) { 99913727Sroot jobnum = 0; 100013727Sroot do 100113727Sroot jobnum = jobnum * 10 + (*job++ - '0'); 100213727Sroot while (isdigit(*job)); 100315719Sralph for (qq = queue + nitems; --qq >= queue; ) { 100413727Sroot n = 0; 100515719Sralph for (cp = (*qq)->q_name+3; isdigit(*cp); ) 100614151Sralph n = n * 10 + (*cp++ - '0'); 100715719Sralph if (jobnum != n) 100815719Sralph continue; 100915719Sralph if (*job && strcmp(job, cp) != 0) 101015719Sralph continue; 101115719Sralph if (machine != NULL && strcmp(machine, cp) != 0) 101215719Sralph continue; 101315719Sralph if (touch(*qq) == 0) { 101415719Sralph printf("\tmoved %s\n", (*qq)->q_name); 101515719Sralph cnt++; 101615719Sralph } 101713727Sroot } 101815719Sralph return(cnt); 101915719Sralph } 102015719Sralph /* 102115719Sralph * Process item consisting of owner's name (example: henry). 102215719Sralph */ 102315719Sralph for (qq = queue + nitems; --qq >= queue; ) { 102415719Sralph if ((fp = fopen((*qq)->q_name, "r")) == NULL) 102513727Sroot continue; 102615719Sralph while (getline(fp) > 0) 102715719Sralph if (line[0] == 'P') 102815719Sralph break; 102915719Sralph (void) fclose(fp); 103015719Sralph if (line[0] != 'P' || strcmp(job, line+1) != 0) 103115719Sralph continue; 103215719Sralph if (touch(*qq) == 0) { 103315719Sralph printf("\tmoved %s\n", (*qq)->q_name); 103415719Sralph cnt++; 103513727Sroot } 103613727Sroot } 103715719Sralph return(cnt); 103813727Sroot } 103916755Sralph 104016755Sralph /* 104116755Sralph * Enable everything and start printer (undo `down'). 104216755Sralph */ 104355472Sbostic void 104416755Sralph up(argc, argv) 104555472Sbostic int argc; 104616755Sralph char *argv[]; 104716755Sralph { 104816755Sralph register int c, status; 104916755Sralph register char *cp1, *cp2; 105016755Sralph char prbuf[100]; 105116755Sralph 105216755Sralph if (argc == 1) { 105316755Sralph printf("Usage: up {all | printer ...}\n"); 105416755Sralph return; 105516755Sralph } 105616755Sralph if (argc == 2 && !strcmp(argv[1], "all")) { 105716755Sralph printer = prbuf; 105856121Selan while (cgetnext(&bp, printcapdb) > 0) { 105916755Sralph cp1 = prbuf; 106056121Selan cp2 = bp; 106116755Sralph while ((c = *cp2++) && c != '|' && c != ':') 106216755Sralph *cp1++ = c; 106316755Sralph *cp1 = '\0'; 106416755Sralph startpr(2); 106516755Sralph } 106616755Sralph return; 106716755Sralph } 106816755Sralph while (--argc) { 106916755Sralph printer = *++argv; 107056121Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) { 107116755Sralph printf("cannot open printer description file\n"); 107216755Sralph continue; 107356121Selan } else if (status == -1) { 107416755Sralph printf("unknown printer %s\n", printer); 107516755Sralph continue; 107656121Selan } else if (status == -3) 107756121Selan fatal("potential reference loop detected in printcap file"); 107856121Selan 107916755Sralph startpr(2); 108016755Sralph } 108116755Sralph } 1082