1dea673e9SRodney W. Grimes /* 2dea673e9SRodney W. Grimes * Copyright (c) 1983, 1993 3dea673e9SRodney W. Grimes * The Regents of the University of California. All rights reserved. 4dea673e9SRodney W. Grimes * 5dea673e9SRodney W. Grimes * 6dea673e9SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 7dea673e9SRodney W. Grimes * modification, are permitted provided that the following conditions 8dea673e9SRodney W. Grimes * are met: 9dea673e9SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 10dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 11dea673e9SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 12dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 13dea673e9SRodney W. Grimes * documentation and/or other materials provided with the distribution. 14dea673e9SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 15dea673e9SRodney W. Grimes * must display the following acknowledgement: 16dea673e9SRodney W. Grimes * This product includes software developed by the University of 17dea673e9SRodney W. Grimes * California, Berkeley and its contributors. 18dea673e9SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 19dea673e9SRodney W. Grimes * may be used to endorse or promote products derived from this software 20dea673e9SRodney W. Grimes * without specific prior written permission. 21dea673e9SRodney W. Grimes * 22dea673e9SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23dea673e9SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24dea673e9SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25dea673e9SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26dea673e9SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27dea673e9SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28dea673e9SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29dea673e9SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30dea673e9SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31dea673e9SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32dea673e9SRodney W. Grimes * SUCH DAMAGE. 33dea673e9SRodney W. Grimes */ 34dea673e9SRodney W. Grimes 35dea673e9SRodney W. Grimes #ifndef lint 364a1a0dbeSGarrett Wollman static const char copyright[] = 37dea673e9SRodney W. Grimes "@(#) Copyright (c) 1983, 1993\n\ 38dea673e9SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 39dea673e9SRodney W. Grimes #endif /* not lint */ 40dea673e9SRodney W. Grimes 41dea673e9SRodney W. Grimes #ifndef lint 424a1a0dbeSGarrett Wollman /* 435458e2f4SJoerg Wunsch static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95"; 444a1a0dbeSGarrett Wollman */ 454a1a0dbeSGarrett Wollman static const char rcsid[] = 464a1a0dbeSGarrett Wollman "$Id$"; 47dea673e9SRodney W. Grimes #endif /* not lint */ 48dea673e9SRodney W. Grimes 49dea673e9SRodney W. Grimes /* 50dea673e9SRodney W. Grimes * lpc -- line printer control program -- commands: 51dea673e9SRodney W. Grimes */ 52dea673e9SRodney W. Grimes 53dea673e9SRodney W. Grimes #include <sys/param.h> 54dea673e9SRodney W. Grimes #include <sys/time.h> 55dea673e9SRodney W. Grimes #include <sys/stat.h> 565458e2f4SJoerg Wunsch #include <sys/file.h> 57dea673e9SRodney W. Grimes 58dea673e9SRodney W. Grimes #include <signal.h> 59dea673e9SRodney W. Grimes #include <fcntl.h> 60dea673e9SRodney W. Grimes #include <errno.h> 61dea673e9SRodney W. Grimes #include <dirent.h> 62dea673e9SRodney W. Grimes #include <unistd.h> 63dea673e9SRodney W. Grimes #include <stdlib.h> 64dea673e9SRodney W. Grimes #include <stdio.h> 65dea673e9SRodney W. Grimes #include <ctype.h> 66dea673e9SRodney W. Grimes #include <string.h> 67dea673e9SRodney W. Grimes #include "lp.h" 68dea673e9SRodney W. Grimes #include "lp.local.h" 69dea673e9SRodney W. Grimes #include "lpc.h" 70dea673e9SRodney W. Grimes #include "extern.h" 71dea673e9SRodney W. Grimes #include "pathnames.h" 72dea673e9SRodney W. Grimes 73360d4ad5SWarner Losh extern uid_t uid, euid; 74360d4ad5SWarner Losh 754a1a0dbeSGarrett Wollman static void abortpr __P((struct printer *, int)); 76dea673e9SRodney W. Grimes static int doarg __P((char *)); 77dea673e9SRodney W. Grimes static int doselect __P((struct dirent *)); 784a1a0dbeSGarrett Wollman static void putmsg __P((struct printer *, int, char **)); 79dea673e9SRodney W. Grimes static int sortq __P((const void *, const void *)); 804a1a0dbeSGarrett Wollman static void startpr __P((struct printer *, int)); 81dea673e9SRodney W. Grimes static int touch __P((struct queue *)); 82dea673e9SRodney W. Grimes static void unlinkf __P((char *)); 834a1a0dbeSGarrett Wollman static void upstat __P((struct printer *, char *)); 844a1a0dbeSGarrett Wollman 854a1a0dbeSGarrett Wollman /* 864a1a0dbeSGarrett Wollman * generic framework for commands which operate on all or a specified 874a1a0dbeSGarrett Wollman * set of printers 884a1a0dbeSGarrett Wollman */ 894a1a0dbeSGarrett Wollman void 904a1a0dbeSGarrett Wollman generic(doit, argc, argv) 914a1a0dbeSGarrett Wollman void (*doit) __P((struct printer *)); 924a1a0dbeSGarrett Wollman int argc; 934a1a0dbeSGarrett Wollman char *argv[]; 944a1a0dbeSGarrett Wollman { 954a1a0dbeSGarrett Wollman int status, more; 964a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 974a1a0dbeSGarrett Wollman 984a1a0dbeSGarrett Wollman if (argc == 1) { 994a1a0dbeSGarrett Wollman printf("Usage: %s {all | printer ...}\n", argv[0]); 1004a1a0dbeSGarrett Wollman return; 1014a1a0dbeSGarrett Wollman } 1024a1a0dbeSGarrett Wollman if (argc == 2 && strcmp(argv[1], "all") == 0) { 1034a1a0dbeSGarrett Wollman more = firstprinter(pp, &status); 1044a1a0dbeSGarrett Wollman if (status) 1054a1a0dbeSGarrett Wollman goto looperr; 1064a1a0dbeSGarrett Wollman while (more) { 1074a1a0dbeSGarrett Wollman (*doit)(pp); 1084a1a0dbeSGarrett Wollman do { 1094a1a0dbeSGarrett Wollman more = nextprinter(pp, &status); 1104a1a0dbeSGarrett Wollman looperr: 1114a1a0dbeSGarrett Wollman switch (status) { 1124a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 1134a1a0dbeSGarrett Wollman printf("warning: %s: unresolved " 1144a1a0dbeSGarrett Wollman "tc= reference(s) ", 1154a1a0dbeSGarrett Wollman pp->printer); 1164a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 1174a1a0dbeSGarrett Wollman break; 1184a1a0dbeSGarrett Wollman default: 1194a1a0dbeSGarrett Wollman fatal(pp, pcaperr(status)); 1204a1a0dbeSGarrett Wollman } 1214a1a0dbeSGarrett Wollman } while (more && status); 1224a1a0dbeSGarrett Wollman } 1234a1a0dbeSGarrett Wollman return; 1244a1a0dbeSGarrett Wollman } 1254a1a0dbeSGarrett Wollman while (--argc) { 1264a1a0dbeSGarrett Wollman ++argv; 1274a1a0dbeSGarrett Wollman init_printer(pp); 1284a1a0dbeSGarrett Wollman status = getprintcap(*argv, pp); 1294a1a0dbeSGarrett Wollman switch(status) { 1304a1a0dbeSGarrett Wollman default: 1314a1a0dbeSGarrett Wollman fatal(pp, pcaperr(status)); 1324a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 1334a1a0dbeSGarrett Wollman printf("unknown printer %s\n", *argv); 1344a1a0dbeSGarrett Wollman continue; 1354a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 1364a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)\n", 1374a1a0dbeSGarrett Wollman *argv); 1384a1a0dbeSGarrett Wollman break; 1394a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 1404a1a0dbeSGarrett Wollman break; 1414a1a0dbeSGarrett Wollman } 1424a1a0dbeSGarrett Wollman (*doit)(pp); 1434a1a0dbeSGarrett Wollman } 1444a1a0dbeSGarrett Wollman } 145dea673e9SRodney W. Grimes 146dea673e9SRodney W. Grimes /* 147dea673e9SRodney W. Grimes * kill an existing daemon and disable printing. 148dea673e9SRodney W. Grimes */ 149dea673e9SRodney W. Grimes void 1504a1a0dbeSGarrett Wollman doabort(pp) 1514a1a0dbeSGarrett Wollman struct printer *pp; 152dea673e9SRodney W. Grimes { 1534a1a0dbeSGarrett Wollman abortpr(pp, 1); 154dea673e9SRodney W. Grimes } 155dea673e9SRodney W. Grimes 156dea673e9SRodney W. Grimes static void 1574a1a0dbeSGarrett Wollman abortpr(pp, dis) 1584a1a0dbeSGarrett Wollman struct printer *pp; 159dea673e9SRodney W. Grimes int dis; 160dea673e9SRodney W. Grimes { 161dea673e9SRodney W. Grimes register FILE *fp; 162dea673e9SRodney W. Grimes struct stat stbuf; 163dea673e9SRodney W. Grimes int pid, fd; 1644a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 165dea673e9SRodney W. Grimes 1664a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 1674a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 168dea673e9SRodney W. Grimes 169dea673e9SRodney W. Grimes /* 170dea673e9SRodney W. Grimes * Turn on the owner execute bit of the lock file to disable printing. 171dea673e9SRodney W. Grimes */ 172dea673e9SRodney W. Grimes if (dis) { 173360d4ad5SWarner Losh seteuid(euid); 1744a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 1754a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 1764a1a0dbeSGarrett Wollman printf("\tcannot disable printing: %s\n", 1774a1a0dbeSGarrett Wollman strerror(errno)); 178dea673e9SRodney W. Grimes else { 1794a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 180dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 181dea673e9SRodney W. Grimes } 182dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 1834a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 1844a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 1854a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 1864a1a0dbeSGarrett Wollman strerror(errno)); 187dea673e9SRodney W. Grimes else { 188dea673e9SRodney W. Grimes (void) close(fd); 1894a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 190dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 191dea673e9SRodney W. Grimes printf("\tno daemon to abort\n"); 192dea673e9SRodney W. Grimes } 193360d4ad5SWarner Losh goto out; 194dea673e9SRodney W. Grimes } else { 195dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 196360d4ad5SWarner Losh goto out; 197dea673e9SRodney W. Grimes } 198dea673e9SRodney W. Grimes } 199dea673e9SRodney W. Grimes /* 200dea673e9SRodney W. Grimes * Kill the current daemon to stop printing now. 201dea673e9SRodney W. Grimes */ 2024a1a0dbeSGarrett Wollman if ((fp = fopen(lf, "r")) == NULL) { 203dea673e9SRodney W. Grimes printf("\tcannot open lock file\n"); 204360d4ad5SWarner Losh goto out; 205dea673e9SRodney W. Grimes } 206dea673e9SRodney W. Grimes if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 207dea673e9SRodney W. Grimes (void) fclose(fp); /* unlocks as well */ 208dea673e9SRodney W. Grimes printf("\tno daemon to abort\n"); 209360d4ad5SWarner Losh goto out; 210dea673e9SRodney W. Grimes } 211dea673e9SRodney W. Grimes (void) fclose(fp); 212360d4ad5SWarner Losh if (kill(pid = atoi(line), SIGTERM) < 0) { 213360d4ad5SWarner Losh if (errno == ESRCH) 214360d4ad5SWarner Losh printf("\tno daemon to abort\n"); 215dea673e9SRodney W. Grimes else 216360d4ad5SWarner Losh printf("\tWarning: daemon (pid %d) not killed\n", pid); 217360d4ad5SWarner Losh } else 218dea673e9SRodney W. Grimes printf("\tdaemon (pid %d) killed\n", pid); 219360d4ad5SWarner Losh out: 220360d4ad5SWarner Losh seteuid(uid); 221dea673e9SRodney W. Grimes } 222dea673e9SRodney W. Grimes 223dea673e9SRodney W. Grimes /* 224dea673e9SRodney W. Grimes * Write a message into the status file. 225dea673e9SRodney W. Grimes */ 226dea673e9SRodney W. Grimes static void 2274a1a0dbeSGarrett Wollman upstat(pp, msg) 2284a1a0dbeSGarrett Wollman struct printer *pp; 229dea673e9SRodney W. Grimes char *msg; 230dea673e9SRodney W. Grimes { 231dea673e9SRodney W. Grimes register int fd; 2325f87a7b6SWarner Losh char statfile[MAXPATHLEN]; 233dea673e9SRodney W. Grimes 2344a1a0dbeSGarrett Wollman status_file_name(pp, statfile, sizeof statfile); 235dea673e9SRodney W. Grimes umask(0); 2364a1a0dbeSGarrett Wollman fd = open(statfile, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 2374a1a0dbeSGarrett Wollman if (fd < 0) { 2384a1a0dbeSGarrett Wollman printf("\tcannot create status file: %s\n", strerror(errno)); 239dea673e9SRodney W. Grimes return; 240dea673e9SRodney W. Grimes } 241dea673e9SRodney W. Grimes (void) ftruncate(fd, 0); 242dea673e9SRodney W. Grimes if (msg == (char *)NULL) 243dea673e9SRodney W. Grimes (void) write(fd, "\n", 1); 244dea673e9SRodney W. Grimes else 245dea673e9SRodney W. Grimes (void) write(fd, msg, strlen(msg)); 246dea673e9SRodney W. Grimes (void) close(fd); 247dea673e9SRodney W. Grimes } 248dea673e9SRodney W. Grimes 249dea673e9SRodney W. Grimes static int 250dea673e9SRodney W. Grimes doselect(d) 251dea673e9SRodney W. Grimes struct dirent *d; 252dea673e9SRodney W. Grimes { 253dea673e9SRodney W. Grimes int c = d->d_name[0]; 254dea673e9SRodney W. Grimes 255dea673e9SRodney W. Grimes if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 256dea673e9SRodney W. Grimes return(1); 257dea673e9SRodney W. Grimes return(0); 258dea673e9SRodney W. Grimes } 259dea673e9SRodney W. Grimes 260dea673e9SRodney W. Grimes /* 261dea673e9SRodney W. Grimes * Comparison routine for scandir. Sort by job number and machine, then 262dea673e9SRodney W. Grimes * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 263dea673e9SRodney W. Grimes */ 264dea673e9SRodney W. Grimes static int 265dea673e9SRodney W. Grimes sortq(a, b) 266dea673e9SRodney W. Grimes const void *a, *b; 267dea673e9SRodney W. Grimes { 268dea673e9SRodney W. Grimes struct dirent **d1, **d2; 269dea673e9SRodney W. Grimes int c1, c2; 270dea673e9SRodney W. Grimes 271dea673e9SRodney W. Grimes d1 = (struct dirent **)a; 272dea673e9SRodney W. Grimes d2 = (struct dirent **)b; 273bc407914SWarner Losh if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))) 274dea673e9SRodney W. Grimes return(c1); 275dea673e9SRodney W. Grimes c1 = (*d1)->d_name[0]; 276dea673e9SRodney W. Grimes c2 = (*d2)->d_name[0]; 277dea673e9SRodney W. Grimes if (c1 == c2) 278dea673e9SRodney W. Grimes return((*d1)->d_name[2] - (*d2)->d_name[2]); 279dea673e9SRodney W. Grimes if (c1 == 'c') 280dea673e9SRodney W. Grimes return(-1); 281dea673e9SRodney W. Grimes if (c1 == 'd' || c2 == 'c') 282dea673e9SRodney W. Grimes return(1); 283dea673e9SRodney W. Grimes return(-1); 284dea673e9SRodney W. Grimes } 285dea673e9SRodney W. Grimes 286dea673e9SRodney W. Grimes /* 2874a1a0dbeSGarrett Wollman * Remove all spool files and temporaries from the spooling area. 2884a1a0dbeSGarrett Wollman * Or, perhaps: 289dea673e9SRodney W. Grimes * Remove incomplete jobs from spooling area. 290dea673e9SRodney W. Grimes */ 2914a1a0dbeSGarrett Wollman void 2924a1a0dbeSGarrett Wollman clean(pp) 2934a1a0dbeSGarrett Wollman struct printer *pp; 294dea673e9SRodney W. Grimes { 295dea673e9SRodney W. Grimes register int i, n; 296dea673e9SRodney W. Grimes register char *cp, *cp1, *lp; 297dea673e9SRodney W. Grimes struct dirent **queue; 298dea673e9SRodney W. Grimes int nitems; 299dea673e9SRodney W. Grimes 3004a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 301dea673e9SRodney W. Grimes 3024a1a0dbeSGarrett Wollman lp = line; 3034a1a0dbeSGarrett Wollman cp = pp->spool_dir; 3044a1a0dbeSGarrett Wollman while (lp < &line[sizeof(line) - 1]) { 3054a1a0dbeSGarrett Wollman if ((*lp++ = *cp++) == 0) 3064a1a0dbeSGarrett Wollman break; 3074a1a0dbeSGarrett Wollman } 308dea673e9SRodney W. Grimes lp[-1] = '/'; 309dea673e9SRodney W. Grimes 310360d4ad5SWarner Losh seteuid(euid); 3114a1a0dbeSGarrett Wollman nitems = scandir(pp->spool_dir, &queue, doselect, sortq); 312360d4ad5SWarner Losh seteuid(uid); 313dea673e9SRodney W. Grimes if (nitems < 0) { 314dea673e9SRodney W. Grimes printf("\tcannot examine spool directory\n"); 315dea673e9SRodney W. Grimes return; 316dea673e9SRodney W. Grimes } 317dea673e9SRodney W. Grimes if (nitems == 0) 318dea673e9SRodney W. Grimes return; 319dea673e9SRodney W. Grimes i = 0; 320dea673e9SRodney W. Grimes do { 321dea673e9SRodney W. Grimes cp = queue[i]->d_name; 322dea673e9SRodney W. Grimes if (*cp == 'c') { 323dea673e9SRodney W. Grimes n = 0; 324dea673e9SRodney W. Grimes while (i + 1 < nitems) { 325dea673e9SRodney W. Grimes cp1 = queue[i + 1]->d_name; 326dea673e9SRodney W. Grimes if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 327dea673e9SRodney W. Grimes break; 328dea673e9SRodney W. Grimes i++; 329dea673e9SRodney W. Grimes n++; 330dea673e9SRodney W. Grimes } 331dea673e9SRodney W. Grimes if (n == 0) { 33287751a84SWarner Losh strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 33387751a84SWarner Losh line[sizeof(line) - 1] = '\0'; 334dea673e9SRodney W. Grimes unlinkf(line); 335dea673e9SRodney W. Grimes } 336dea673e9SRodney W. Grimes } else { 337dea673e9SRodney W. Grimes /* 338dea673e9SRodney W. Grimes * Must be a df with no cf (otherwise, it would have 339dea673e9SRodney W. Grimes * been skipped above) or a tf file (which can always 340dea673e9SRodney W. Grimes * be removed). 341dea673e9SRodney W. Grimes */ 34287751a84SWarner Losh strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 34387751a84SWarner Losh line[sizeof(line) - 1] = '\0'; 344dea673e9SRodney W. Grimes unlinkf(line); 345dea673e9SRodney W. Grimes } 346dea673e9SRodney W. Grimes } while (++i < nitems); 347dea673e9SRodney W. Grimes } 348dea673e9SRodney W. Grimes 349dea673e9SRodney W. Grimes static void 350dea673e9SRodney W. Grimes unlinkf(name) 351dea673e9SRodney W. Grimes char *name; 352dea673e9SRodney W. Grimes { 353360d4ad5SWarner Losh seteuid(euid); 354dea673e9SRodney W. Grimes if (unlink(name) < 0) 355dea673e9SRodney W. Grimes printf("\tcannot remove %s\n", name); 356dea673e9SRodney W. Grimes else 357dea673e9SRodney W. Grimes printf("\tremoved %s\n", name); 358360d4ad5SWarner Losh seteuid(uid); 359dea673e9SRodney W. Grimes } 360dea673e9SRodney W. Grimes 361dea673e9SRodney W. Grimes /* 362dea673e9SRodney W. Grimes * Enable queuing to the printer (allow lpr's). 363dea673e9SRodney W. Grimes */ 364dea673e9SRodney W. Grimes void 3654a1a0dbeSGarrett Wollman enable(pp) 3664a1a0dbeSGarrett Wollman struct printer *pp; 367dea673e9SRodney W. Grimes { 368dea673e9SRodney W. Grimes struct stat stbuf; 3694a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 370dea673e9SRodney W. Grimes 3714a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 3724a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 373dea673e9SRodney W. Grimes 374dea673e9SRodney W. Grimes /* 375dea673e9SRodney W. Grimes * Turn off the group execute bit of the lock file to enable queuing. 376dea673e9SRodney W. Grimes */ 377360d4ad5SWarner Losh seteuid(euid); 3784a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 3794a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode & ~LFM_QUEUE_DIS) < 0) 380dea673e9SRodney W. Grimes printf("\tcannot enable queuing\n"); 381dea673e9SRodney W. Grimes else 382dea673e9SRodney W. Grimes printf("\tqueuing enabled\n"); 383dea673e9SRodney W. Grimes } 384360d4ad5SWarner Losh seteuid(uid); 385dea673e9SRodney W. Grimes } 386dea673e9SRodney W. Grimes 387dea673e9SRodney W. Grimes /* 388dea673e9SRodney W. Grimes * Disable queuing. 389dea673e9SRodney W. Grimes */ 390dea673e9SRodney W. Grimes void 3914a1a0dbeSGarrett Wollman disable(pp) 3924a1a0dbeSGarrett Wollman struct printer *pp; 393dea673e9SRodney W. Grimes { 394dea673e9SRodney W. Grimes register int fd; 395dea673e9SRodney W. Grimes struct stat stbuf; 3964a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 397dea673e9SRodney W. Grimes 3984a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 3994a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 400dea673e9SRodney W. Grimes /* 401dea673e9SRodney W. Grimes * Turn on the group execute bit of the lock file to disable queuing. 402dea673e9SRodney W. Grimes */ 403360d4ad5SWarner Losh seteuid(euid); 4044a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 4054a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_QUEUE_DIS) < 0) 4064a1a0dbeSGarrett Wollman printf("\tcannot disable queuing: %s\n", 4074a1a0dbeSGarrett Wollman strerror(errno)); 408dea673e9SRodney W. Grimes else 409dea673e9SRodney W. Grimes printf("\tqueuing disabled\n"); 410dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 4114a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 4124a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_QUEUE_DIS)) < 0) 4134a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 4144a1a0dbeSGarrett Wollman strerror(errno)); 415dea673e9SRodney W. Grimes else { 416dea673e9SRodney W. Grimes (void) close(fd); 417dea673e9SRodney W. Grimes printf("\tqueuing disabled\n"); 418dea673e9SRodney W. Grimes } 419dea673e9SRodney W. Grimes } else 420dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 421360d4ad5SWarner Losh seteuid(uid); 422dea673e9SRodney W. Grimes } 423dea673e9SRodney W. Grimes 424dea673e9SRodney W. Grimes /* 425dea673e9SRodney W. Grimes * Disable queuing and printing and put a message into the status file 426dea673e9SRodney W. Grimes * (reason for being down). 427dea673e9SRodney W. Grimes */ 428dea673e9SRodney W. Grimes void 429dea673e9SRodney W. Grimes down(argc, argv) 430dea673e9SRodney W. Grimes int argc; 431dea673e9SRodney W. Grimes char *argv[]; 432dea673e9SRodney W. Grimes { 4334a1a0dbeSGarrett Wollman int status, more; 4344a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 435dea673e9SRodney W. Grimes 436dea673e9SRodney W. Grimes if (argc == 1) { 437dea673e9SRodney W. Grimes printf("Usage: down {all | printer} [message ...]\n"); 438dea673e9SRodney W. Grimes return; 439dea673e9SRodney W. Grimes } 440dea673e9SRodney W. Grimes if (!strcmp(argv[1], "all")) { 4414a1a0dbeSGarrett Wollman more = firstprinter(pp, &status); 4424a1a0dbeSGarrett Wollman if (status) 4434a1a0dbeSGarrett Wollman goto looperr; 4444a1a0dbeSGarrett Wollman while (more) { 4454a1a0dbeSGarrett Wollman putmsg(pp, argc - 2, argv + 2); 4464a1a0dbeSGarrett Wollman do { 4474a1a0dbeSGarrett Wollman more = nextprinter(pp, &status); 4484a1a0dbeSGarrett Wollman looperr: 4494a1a0dbeSGarrett Wollman switch (status) { 4504a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 4514a1a0dbeSGarrett Wollman printf("warning: %s: unresolved " 4524a1a0dbeSGarrett Wollman "tc= reference(s) ", 4534a1a0dbeSGarrett Wollman pp->printer); 4544a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 4554a1a0dbeSGarrett Wollman break; 4564a1a0dbeSGarrett Wollman default: 4574a1a0dbeSGarrett Wollman fatal(pp, pcaperr(status)); 4584a1a0dbeSGarrett Wollman } 4594a1a0dbeSGarrett Wollman } while (more && status); 460dea673e9SRodney W. Grimes } 461dea673e9SRodney W. Grimes return; 462dea673e9SRodney W. Grimes } 4634a1a0dbeSGarrett Wollman init_printer(pp); 4644a1a0dbeSGarrett Wollman status = getprintcap(argv[1], pp); 4654a1a0dbeSGarrett Wollman switch(status) { 4664a1a0dbeSGarrett Wollman default: 4674a1a0dbeSGarrett Wollman fatal(pp, pcaperr(status)); 4684a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 4694a1a0dbeSGarrett Wollman printf("unknown printer %s\n", argv[1]); 470dea673e9SRodney W. Grimes return; 4714a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 4724a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)", argv[1]); 4734a1a0dbeSGarrett Wollman break; 4744a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 4754a1a0dbeSGarrett Wollman break; 4764a1a0dbeSGarrett Wollman } 4774a1a0dbeSGarrett Wollman putmsg(pp, argc - 2, argv + 2); 478dea673e9SRodney W. Grimes } 479dea673e9SRodney W. Grimes 480dea673e9SRodney W. Grimes static void 4814a1a0dbeSGarrett Wollman putmsg(pp, argc, argv) 4824a1a0dbeSGarrett Wollman struct printer *pp; 483dea673e9SRodney W. Grimes int argc; 484dea673e9SRodney W. Grimes char **argv; 485dea673e9SRodney W. Grimes { 486dea673e9SRodney W. Grimes register int fd; 487dea673e9SRodney W. Grimes register char *cp1, *cp2; 488dea673e9SRodney W. Grimes char buf[1024]; 4894a1a0dbeSGarrett Wollman char file[MAXPATHLEN]; 490dea673e9SRodney W. Grimes struct stat stbuf; 491dea673e9SRodney W. Grimes 4924a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 493dea673e9SRodney W. Grimes /* 4944a1a0dbeSGarrett Wollman * Turn on the group execute bit of the lock file to disable queuing; 495dea673e9SRodney W. Grimes * turn on the owner execute bit of the lock file to disable printing. 496dea673e9SRodney W. Grimes */ 4974a1a0dbeSGarrett Wollman lock_file_name(pp, file, sizeof file); 498360d4ad5SWarner Losh seteuid(euid); 4994a1a0dbeSGarrett Wollman if (stat(file, &stbuf) >= 0) { 5004a1a0dbeSGarrett Wollman if (chmod(file, stbuf.st_mode|LFM_PRINT_DIS|LFM_QUEUE_DIS) < 0) 5014a1a0dbeSGarrett Wollman printf("\tcannot disable queuing: %s\n", 5024a1a0dbeSGarrett Wollman strerror(errno)); 503dea673e9SRodney W. Grimes else 504dea673e9SRodney W. Grimes printf("\tprinter and queuing disabled\n"); 505dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 5064a1a0dbeSGarrett Wollman if ((fd = open(file, O_WRONLY|O_CREAT, 5074a1a0dbeSGarrett Wollman LOCK_FILE_MODE|LFM_PRINT_DIS|LFM_QUEUE_DIS)) < 0) 5084a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 5094a1a0dbeSGarrett Wollman strerror(errno)); 510dea673e9SRodney W. Grimes else { 511dea673e9SRodney W. Grimes (void) close(fd); 512dea673e9SRodney W. Grimes printf("\tprinter and queuing disabled\n"); 513dea673e9SRodney W. Grimes } 514360d4ad5SWarner Losh seteuid(uid); 515dea673e9SRodney W. Grimes return; 516dea673e9SRodney W. Grimes } else 517dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 518dea673e9SRodney W. Grimes /* 519dea673e9SRodney W. Grimes * Write the message into the status file. 520dea673e9SRodney W. Grimes */ 5214a1a0dbeSGarrett Wollman status_file_name(pp, file, sizeof file); 5224a1a0dbeSGarrett Wollman fd = open(file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 5234a1a0dbeSGarrett Wollman if (fd < 0) { 5244a1a0dbeSGarrett Wollman printf("\tcannot create status file: %s\n", strerror(errno)); 525360d4ad5SWarner Losh seteuid(uid); 526dea673e9SRodney W. Grimes return; 527dea673e9SRodney W. Grimes } 528360d4ad5SWarner Losh seteuid(uid); 529dea673e9SRodney W. Grimes (void) ftruncate(fd, 0); 530dea673e9SRodney W. Grimes if (argc <= 0) { 531dea673e9SRodney W. Grimes (void) write(fd, "\n", 1); 532dea673e9SRodney W. Grimes (void) close(fd); 533dea673e9SRodney W. Grimes return; 534dea673e9SRodney W. Grimes } 535dea673e9SRodney W. Grimes cp1 = buf; 536dea673e9SRodney W. Grimes while (--argc >= 0) { 537dea673e9SRodney W. Grimes cp2 = *argv++; 5385f87a7b6SWarner Losh while ((cp1 - buf) < sizeof(buf) && (*cp1++ = *cp2++)) 539dea673e9SRodney W. Grimes ; 540dea673e9SRodney W. Grimes cp1[-1] = ' '; 541dea673e9SRodney W. Grimes } 542dea673e9SRodney W. Grimes cp1[-1] = '\n'; 543dea673e9SRodney W. Grimes *cp1 = '\0'; 544dea673e9SRodney W. Grimes (void) write(fd, buf, strlen(buf)); 545dea673e9SRodney W. Grimes (void) close(fd); 546dea673e9SRodney W. Grimes } 547dea673e9SRodney W. Grimes 548dea673e9SRodney W. Grimes /* 549dea673e9SRodney W. Grimes * Exit lpc 550dea673e9SRodney W. Grimes */ 551dea673e9SRodney W. Grimes void 552dea673e9SRodney W. Grimes quit(argc, argv) 553dea673e9SRodney W. Grimes int argc; 554dea673e9SRodney W. Grimes char *argv[]; 555dea673e9SRodney W. Grimes { 556dea673e9SRodney W. Grimes exit(0); 557dea673e9SRodney W. Grimes } 558dea673e9SRodney W. Grimes 559dea673e9SRodney W. Grimes /* 560dea673e9SRodney W. Grimes * Kill and restart the daemon. 561dea673e9SRodney W. Grimes */ 562dea673e9SRodney W. Grimes void 5634a1a0dbeSGarrett Wollman restart(pp) 5644a1a0dbeSGarrett Wollman struct printer *pp; 565dea673e9SRodney W. Grimes { 5664a1a0dbeSGarrett Wollman abortpr(pp, 0); 5674a1a0dbeSGarrett Wollman startpr(pp, 0); 568dea673e9SRodney W. Grimes } 569dea673e9SRodney W. Grimes 570dea673e9SRodney W. Grimes /* 571dea673e9SRodney W. Grimes * Enable printing on the specified printer and startup the daemon. 572dea673e9SRodney W. Grimes */ 573dea673e9SRodney W. Grimes void 5744a1a0dbeSGarrett Wollman startcmd(pp) 5754a1a0dbeSGarrett Wollman struct printer *pp; 576dea673e9SRodney W. Grimes { 5774a1a0dbeSGarrett Wollman startpr(pp, 1); 578dea673e9SRodney W. Grimes } 579dea673e9SRodney W. Grimes 580dea673e9SRodney W. Grimes static void 5814a1a0dbeSGarrett Wollman startpr(pp, enable) 5824a1a0dbeSGarrett Wollman struct printer *pp; 583dea673e9SRodney W. Grimes int enable; 584dea673e9SRodney W. Grimes { 585dea673e9SRodney W. Grimes struct stat stbuf; 5864a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 587dea673e9SRodney W. Grimes 5884a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 5894a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 590dea673e9SRodney W. Grimes 591dea673e9SRodney W. Grimes /* 592dea673e9SRodney W. Grimes * Turn off the owner execute bit of the lock file to enable printing. 593dea673e9SRodney W. Grimes */ 594360d4ad5SWarner Losh seteuid(euid); 5954a1a0dbeSGarrett Wollman if (enable && stat(lf, &stbuf) >= 0) { 5964a1a0dbeSGarrett Wollman mode_t bits = (enable == 2 ? 0 5974a1a0dbeSGarrett Wollman : (LFM_PRINT_DIS | LFM_QUEUE_DIS)); 5984a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode & (LOCK_FILE_MODE | bits)) < 0) 599dea673e9SRodney W. Grimes printf("\tcannot enable printing\n"); 600dea673e9SRodney W. Grimes else 601dea673e9SRodney W. Grimes printf("\tprinting enabled\n"); 602dea673e9SRodney W. Grimes } 6034a1a0dbeSGarrett Wollman if (!startdaemon(pp)) 604dea673e9SRodney W. Grimes printf("\tcouldn't start daemon\n"); 605dea673e9SRodney W. Grimes else 606dea673e9SRodney W. Grimes printf("\tdaemon started\n"); 607360d4ad5SWarner Losh seteuid(uid); 608dea673e9SRodney W. Grimes } 609dea673e9SRodney W. Grimes 610dea673e9SRodney W. Grimes /* 611dea673e9SRodney W. Grimes * Print the status of the printer queue. 612dea673e9SRodney W. Grimes */ 6134a1a0dbeSGarrett Wollman void 6144a1a0dbeSGarrett Wollman status(pp) 6154a1a0dbeSGarrett Wollman struct printer *pp; 616dea673e9SRodney W. Grimes { 617dea673e9SRodney W. Grimes struct stat stbuf; 618dea673e9SRodney W. Grimes register int fd, i; 619dea673e9SRodney W. Grimes register struct dirent *dp; 620dea673e9SRodney W. Grimes DIR *dirp; 6214a1a0dbeSGarrett Wollman char file[MAXPATHLEN]; 622dea673e9SRodney W. Grimes 6234a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 6244a1a0dbeSGarrett Wollman lock_file_name(pp, file, sizeof file); 6254a1a0dbeSGarrett Wollman if (stat(file, &stbuf) >= 0) { 626dea673e9SRodney W. Grimes printf("\tqueuing is %s\n", 6274a1a0dbeSGarrett Wollman ((stbuf.st_mode & LFM_QUEUE_DIS) ? "disabled" 6284a1a0dbeSGarrett Wollman : "enabled")); 629dea673e9SRodney W. Grimes printf("\tprinting is %s\n", 6304a1a0dbeSGarrett Wollman ((stbuf.st_mode & LFM_PRINT_DIS) ? "disabled" 6314a1a0dbeSGarrett Wollman : "enabled")); 632dea673e9SRodney W. Grimes } else { 633dea673e9SRodney W. Grimes printf("\tqueuing is enabled\n"); 634dea673e9SRodney W. Grimes printf("\tprinting is enabled\n"); 635dea673e9SRodney W. Grimes } 6364a1a0dbeSGarrett Wollman if ((dirp = opendir(pp->spool_dir)) == NULL) { 637dea673e9SRodney W. Grimes printf("\tcannot examine spool directory\n"); 638dea673e9SRodney W. Grimes return; 639dea673e9SRodney W. Grimes } 640dea673e9SRodney W. Grimes i = 0; 641dea673e9SRodney W. Grimes while ((dp = readdir(dirp)) != NULL) { 642dea673e9SRodney W. Grimes if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 643dea673e9SRodney W. Grimes i++; 644dea673e9SRodney W. Grimes } 645dea673e9SRodney W. Grimes closedir(dirp); 646dea673e9SRodney W. Grimes if (i == 0) 6474a1a0dbeSGarrett Wollman printf("\tno entries in spool area\n"); 648dea673e9SRodney W. Grimes else if (i == 1) 649dea673e9SRodney W. Grimes printf("\t1 entry in spool area\n"); 650dea673e9SRodney W. Grimes else 651dea673e9SRodney W. Grimes printf("\t%d entries in spool area\n", i); 6524a1a0dbeSGarrett Wollman fd = open(file, O_RDONLY); 653dea673e9SRodney W. Grimes if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 654dea673e9SRodney W. Grimes (void) close(fd); /* unlocks as well */ 655bc407914SWarner Losh printf("\tprinter idle\n"); 656dea673e9SRodney W. Grimes return; 657dea673e9SRodney W. Grimes } 658dea673e9SRodney W. Grimes (void) close(fd); 65936abea5dSBrian Somers /* print out the contents of the status file, if it exists */ 6604a1a0dbeSGarrett Wollman status_file_name(pp, file, sizeof file); 6614a1a0dbeSGarrett Wollman fd = open(file, O_RDONLY|O_SHLOCK); 662dea673e9SRodney W. Grimes if (fd >= 0) { 66336abea5dSBrian Somers (void) fstat(fd, &stbuf); 66436abea5dSBrian Somers if (stbuf.st_size > 0) { 66536abea5dSBrian Somers putchar('\t'); 666dea673e9SRodney W. Grimes while ((i = read(fd, line, sizeof(line))) > 0) 667dea673e9SRodney W. Grimes (void) fwrite(line, 1, i, stdout); 66836abea5dSBrian Somers } 669dea673e9SRodney W. Grimes (void) close(fd); /* unlocks as well */ 670dea673e9SRodney W. Grimes } 671dea673e9SRodney W. Grimes } 672dea673e9SRodney W. Grimes 673dea673e9SRodney W. Grimes /* 674dea673e9SRodney W. Grimes * Stop the specified daemon after completing the current job and disable 675dea673e9SRodney W. Grimes * printing. 676dea673e9SRodney W. Grimes */ 677dea673e9SRodney W. Grimes void 6784a1a0dbeSGarrett Wollman stop(pp) 6794a1a0dbeSGarrett Wollman struct printer *pp; 680dea673e9SRodney W. Grimes { 681dea673e9SRodney W. Grimes register int fd; 682dea673e9SRodney W. Grimes struct stat stbuf; 6834a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 684dea673e9SRodney W. Grimes 6854a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 6864a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 687dea673e9SRodney W. Grimes 688dea673e9SRodney W. Grimes /* 689dea673e9SRodney W. Grimes * Turn on the owner execute bit of the lock file to disable printing. 690dea673e9SRodney W. Grimes */ 691360d4ad5SWarner Losh seteuid(euid); 6924a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 6934a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 6944a1a0dbeSGarrett Wollman printf("\tcannot disable printing: %s\n", 6954a1a0dbeSGarrett Wollman strerror(errno)); 696dea673e9SRodney W. Grimes else { 6974a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 698dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 699dea673e9SRodney W. Grimes } 700dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 7014a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 7024a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 7034a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 7044a1a0dbeSGarrett Wollman strerror(errno)); 705dea673e9SRodney W. Grimes else { 706dea673e9SRodney W. Grimes (void) close(fd); 7074a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 708dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 709dea673e9SRodney W. Grimes } 710dea673e9SRodney W. Grimes } else 711dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 712360d4ad5SWarner Losh seteuid(uid); 713dea673e9SRodney W. Grimes } 714dea673e9SRodney W. Grimes 715dea673e9SRodney W. Grimes struct queue **queue; 716dea673e9SRodney W. Grimes int nitems; 717dea673e9SRodney W. Grimes time_t mtime; 718dea673e9SRodney W. Grimes 719dea673e9SRodney W. Grimes /* 720dea673e9SRodney W. Grimes * Put the specified jobs at the top of printer queue. 721dea673e9SRodney W. Grimes */ 722dea673e9SRodney W. Grimes void 723dea673e9SRodney W. Grimes topq(argc, argv) 724dea673e9SRodney W. Grimes int argc; 725dea673e9SRodney W. Grimes char *argv[]; 726dea673e9SRodney W. Grimes { 727dea673e9SRodney W. Grimes register int i; 728dea673e9SRodney W. Grimes struct stat stbuf; 729dea673e9SRodney W. Grimes int status, changed; 7304a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 731dea673e9SRodney W. Grimes 732dea673e9SRodney W. Grimes if (argc < 3) { 733dea673e9SRodney W. Grimes printf("Usage: topq printer [jobnum ...] [user ...]\n"); 734dea673e9SRodney W. Grimes return; 735dea673e9SRodney W. Grimes } 736dea673e9SRodney W. Grimes 737dea673e9SRodney W. Grimes --argc; 7384a1a0dbeSGarrett Wollman ++argv; 7394a1a0dbeSGarrett Wollman init_printer(pp); 7404a1a0dbeSGarrett Wollman status = getprintcap(*argv, pp); 7414a1a0dbeSGarrett Wollman switch(status) { 7424a1a0dbeSGarrett Wollman default: 7434a1a0dbeSGarrett Wollman fatal(pp, pcaperr(status)); 7444a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 7454a1a0dbeSGarrett Wollman printf("unknown printer %s\n", *argv); 746dea673e9SRodney W. Grimes return; 7474a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 7484a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)", *argv); 7494a1a0dbeSGarrett Wollman break; 7504a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 7514a1a0dbeSGarrett Wollman break; 7524a1a0dbeSGarrett Wollman } 7534a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 754dea673e9SRodney W. Grimes 755360d4ad5SWarner Losh seteuid(euid); 7564a1a0dbeSGarrett Wollman if (chdir(pp->spool_dir) < 0) { 7574a1a0dbeSGarrett Wollman printf("\tcannot chdir to %s\n", pp->spool_dir); 758360d4ad5SWarner Losh goto out; 759dea673e9SRodney W. Grimes } 760360d4ad5SWarner Losh seteuid(uid); 7614a1a0dbeSGarrett Wollman nitems = getq(pp, &queue); 762dea673e9SRodney W. Grimes if (nitems == 0) 763dea673e9SRodney W. Grimes return; 764dea673e9SRodney W. Grimes changed = 0; 765dea673e9SRodney W. Grimes mtime = queue[0]->q_time; 766dea673e9SRodney W. Grimes for (i = argc; --i; ) { 767dea673e9SRodney W. Grimes if (doarg(argv[i]) == 0) { 768dea673e9SRodney W. Grimes printf("\tjob %s is not in the queue\n", argv[i]); 769dea673e9SRodney W. Grimes continue; 770dea673e9SRodney W. Grimes } else 771dea673e9SRodney W. Grimes changed++; 772dea673e9SRodney W. Grimes } 773dea673e9SRodney W. Grimes for (i = 0; i < nitems; i++) 774dea673e9SRodney W. Grimes free(queue[i]); 775dea673e9SRodney W. Grimes free(queue); 776dea673e9SRodney W. Grimes if (!changed) { 777dea673e9SRodney W. Grimes printf("\tqueue order unchanged\n"); 778dea673e9SRodney W. Grimes return; 779dea673e9SRodney W. Grimes } 780dea673e9SRodney W. Grimes /* 781dea673e9SRodney W. Grimes * Turn on the public execute bit of the lock file to 782dea673e9SRodney W. Grimes * get lpd to rebuild the queue after the current job. 783dea673e9SRodney W. Grimes */ 784360d4ad5SWarner Losh seteuid(euid); 7854a1a0dbeSGarrett Wollman if (changed && stat(pp->lock_file, &stbuf) >= 0) 7864a1a0dbeSGarrett Wollman (void) chmod(pp->lock_file, stbuf.st_mode | LFM_RESET_QUE); 787360d4ad5SWarner Losh 788360d4ad5SWarner Losh out: 789360d4ad5SWarner Losh seteuid(uid); 790dea673e9SRodney W. Grimes } 791dea673e9SRodney W. Grimes 792dea673e9SRodney W. Grimes /* 793dea673e9SRodney W. Grimes * Reposition the job by changing the modification time of 794dea673e9SRodney W. Grimes * the control file. 795dea673e9SRodney W. Grimes */ 796dea673e9SRodney W. Grimes static int 797dea673e9SRodney W. Grimes touch(q) 798dea673e9SRodney W. Grimes struct queue *q; 799dea673e9SRodney W. Grimes { 800dea673e9SRodney W. Grimes struct timeval tvp[2]; 801360d4ad5SWarner Losh int ret; 802dea673e9SRodney W. Grimes 803dea673e9SRodney W. Grimes tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 804dea673e9SRodney W. Grimes tvp[0].tv_usec = tvp[1].tv_usec = 0; 805360d4ad5SWarner Losh seteuid(euid); 806360d4ad5SWarner Losh ret = utimes(q->q_name, tvp); 807360d4ad5SWarner Losh seteuid(uid); 808360d4ad5SWarner Losh return (ret); 809dea673e9SRodney W. Grimes } 810dea673e9SRodney W. Grimes 811dea673e9SRodney W. Grimes /* 812dea673e9SRodney W. Grimes * Checks if specified job name is in the printer's queue. 813dea673e9SRodney W. Grimes * Returns: negative (-1) if argument name is not in the queue. 814dea673e9SRodney W. Grimes */ 815dea673e9SRodney W. Grimes static int 816dea673e9SRodney W. Grimes doarg(job) 817dea673e9SRodney W. Grimes char *job; 818dea673e9SRodney W. Grimes { 819dea673e9SRodney W. Grimes register struct queue **qq; 820dea673e9SRodney W. Grimes register int jobnum, n; 821dea673e9SRodney W. Grimes register char *cp, *machine; 822dea673e9SRodney W. Grimes int cnt = 0; 823dea673e9SRodney W. Grimes FILE *fp; 824dea673e9SRodney W. Grimes 825dea673e9SRodney W. Grimes /* 826dea673e9SRodney W. Grimes * Look for a job item consisting of system name, colon, number 827dea673e9SRodney W. Grimes * (example: ucbarpa:114) 828dea673e9SRodney W. Grimes */ 829f8eb25daSWarner Losh if ((cp = strchr(job, ':')) != NULL) { 830dea673e9SRodney W. Grimes machine = job; 831dea673e9SRodney W. Grimes *cp++ = '\0'; 832dea673e9SRodney W. Grimes job = cp; 833dea673e9SRodney W. Grimes } else 834dea673e9SRodney W. Grimes machine = NULL; 835dea673e9SRodney W. Grimes 836dea673e9SRodney W. Grimes /* 837dea673e9SRodney W. Grimes * Check for job specified by number (example: 112 or 235ucbarpa). 838dea673e9SRodney W. Grimes */ 839dea673e9SRodney W. Grimes if (isdigit(*job)) { 840dea673e9SRodney W. Grimes jobnum = 0; 841dea673e9SRodney W. Grimes do 842dea673e9SRodney W. Grimes jobnum = jobnum * 10 + (*job++ - '0'); 843dea673e9SRodney W. Grimes while (isdigit(*job)); 844dea673e9SRodney W. Grimes for (qq = queue + nitems; --qq >= queue; ) { 845dea673e9SRodney W. Grimes n = 0; 846dea673e9SRodney W. Grimes for (cp = (*qq)->q_name+3; isdigit(*cp); ) 847dea673e9SRodney W. Grimes n = n * 10 + (*cp++ - '0'); 848dea673e9SRodney W. Grimes if (jobnum != n) 849dea673e9SRodney W. Grimes continue; 850dea673e9SRodney W. Grimes if (*job && strcmp(job, cp) != 0) 851dea673e9SRodney W. Grimes continue; 852dea673e9SRodney W. Grimes if (machine != NULL && strcmp(machine, cp) != 0) 853dea673e9SRodney W. Grimes continue; 854dea673e9SRodney W. Grimes if (touch(*qq) == 0) { 855dea673e9SRodney W. Grimes printf("\tmoved %s\n", (*qq)->q_name); 856dea673e9SRodney W. Grimes cnt++; 857dea673e9SRodney W. Grimes } 858dea673e9SRodney W. Grimes } 859dea673e9SRodney W. Grimes return(cnt); 860dea673e9SRodney W. Grimes } 861dea673e9SRodney W. Grimes /* 862dea673e9SRodney W. Grimes * Process item consisting of owner's name (example: henry). 863dea673e9SRodney W. Grimes */ 864dea673e9SRodney W. Grimes for (qq = queue + nitems; --qq >= queue; ) { 865360d4ad5SWarner Losh seteuid(euid); 866360d4ad5SWarner Losh fp = fopen((*qq)->q_name, "r"); 867360d4ad5SWarner Losh seteuid(uid); 868360d4ad5SWarner Losh if (fp == NULL) 869dea673e9SRodney W. Grimes continue; 870dea673e9SRodney W. Grimes while (getline(fp) > 0) 871dea673e9SRodney W. Grimes if (line[0] == 'P') 872dea673e9SRodney W. Grimes break; 873dea673e9SRodney W. Grimes (void) fclose(fp); 874dea673e9SRodney W. Grimes if (line[0] != 'P' || strcmp(job, line+1) != 0) 875dea673e9SRodney W. Grimes continue; 876dea673e9SRodney W. Grimes if (touch(*qq) == 0) { 877dea673e9SRodney W. Grimes printf("\tmoved %s\n", (*qq)->q_name); 878dea673e9SRodney W. Grimes cnt++; 879dea673e9SRodney W. Grimes } 880dea673e9SRodney W. Grimes } 881dea673e9SRodney W. Grimes return(cnt); 882dea673e9SRodney W. Grimes } 883dea673e9SRodney W. Grimes 884dea673e9SRodney W. Grimes /* 885dea673e9SRodney W. Grimes * Enable everything and start printer (undo `down'). 886dea673e9SRodney W. Grimes */ 887dea673e9SRodney W. Grimes void 8884a1a0dbeSGarrett Wollman up(pp) 8894a1a0dbeSGarrett Wollman struct printer *pp; 890dea673e9SRodney W. Grimes { 8914a1a0dbeSGarrett Wollman startpr(pp, 2); 892dea673e9SRodney W. Grimes } 893