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[] = 4697d92980SPeter Wemm "$FreeBSD$"; 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 73e8e715faSGarance A Drosehn /* 74e8e715faSGarance A Drosehn * Return values from kill_qtask(). 75e8e715faSGarance A Drosehn */ 76e8e715faSGarance A Drosehn #define KQT_LFERROR -2 77e8e715faSGarance A Drosehn #define KQT_KILLFAIL -1 78e8e715faSGarance A Drosehn #define KQT_NODAEMON 0 79e8e715faSGarance A Drosehn #define KQT_KILLOK 1 80e8e715faSGarance A Drosehn 81ba7a1ad7SGarance A Drosehn static void abortpr(struct printer *_pp, int _dis); 82ba7a1ad7SGarance A Drosehn static int doarg(char *_job); 83ba7a1ad7SGarance A Drosehn static int doselect(struct dirent *_d); 84e8e715faSGarance A Drosehn static int kill_qtask(const char *lf); 85ba7a1ad7SGarance A Drosehn static void putmsg(struct printer *_pp, int _argc, char **_argv); 86ba7a1ad7SGarance A Drosehn static int sortq(const void *_a, const void *_b); 87ba7a1ad7SGarance A Drosehn static void startpr(struct printer *_pp, int _chgenable); 88ba7a1ad7SGarance A Drosehn static int touch(struct jobqueue *_jq); 89ba7a1ad7SGarance A Drosehn static void unlinkf(char *_name); 90ba7a1ad7SGarance A Drosehn static void upstat(struct printer *_pp, const char *_msg); 91004c9c5dSGarance A Drosehn static void wrapup_clean(int _laststatus); 924a1a0dbeSGarrett Wollman 934a1a0dbeSGarrett Wollman /* 944a1a0dbeSGarrett Wollman * generic framework for commands which operate on all or a specified 954a1a0dbeSGarrett Wollman * set of printers 964a1a0dbeSGarrett Wollman */ 97004c9c5dSGarance A Drosehn enum qsel_val { /* how a given ptr was selected */ 98004c9c5dSGarance A Drosehn QSEL_UNKNOWN = -1, /* ... not selected yet */ 99004c9c5dSGarance A Drosehn QSEL_BYNAME = 0, /* ... user specifed it by name */ 100004c9c5dSGarance A Drosehn QSEL_ALL = 1 /* ... user wants "all" printers */ 101004c9c5dSGarance A Drosehn /* (with more to come) */ 102004c9c5dSGarance A Drosehn }; 103004c9c5dSGarance A Drosehn 104004c9c5dSGarance A Drosehn static enum qsel_val generic_qselect; /* indicates how ptr was selected */ 105004c9c5dSGarance A Drosehn static int generic_initerr; /* result of initrtn processing */ 106004c9c5dSGarance A Drosehn static char *generic_nullarg; 107004c9c5dSGarance A Drosehn static void (*generic_wrapup)(int _last_status); /* perform rtn wrap-up */ 108004c9c5dSGarance A Drosehn 1094a1a0dbeSGarrett Wollman void 110004c9c5dSGarance A Drosehn generic(void (*specificrtn)(struct printer *_pp), 111004c9c5dSGarance A Drosehn void (*initrtn)(int _argc, char *_argv[]), int argc, char *argv[]) 1124a1a0dbeSGarrett Wollman { 113004c9c5dSGarance A Drosehn int cmdstatus, more, targc; 114004c9c5dSGarance A Drosehn struct printer myprinter, *pp; 115004c9c5dSGarance A Drosehn char **targv; 1164a1a0dbeSGarrett Wollman 1174a1a0dbeSGarrett Wollman if (argc == 1) { 118d3974088SDag-Erling Smørgrav printf("usage: %s {all | printer ...}\n", argv[0]); 1194a1a0dbeSGarrett Wollman return; 1204a1a0dbeSGarrett Wollman } 121004c9c5dSGarance A Drosehn 122004c9c5dSGarance A Drosehn /* 123004c9c5dSGarance A Drosehn * The initialization routine for a command might set a generic 124004c9c5dSGarance A Drosehn * "wrapup" routine, which should be called after processing all 125004c9c5dSGarance A Drosehn * the printers in the command. This might print summary info. 126004c9c5dSGarance A Drosehn * 127004c9c5dSGarance A Drosehn * Note that the initialization routine may also parse (and 128004c9c5dSGarance A Drosehn * nullify) some of the parameters given on the command, leaving 129004c9c5dSGarance A Drosehn * only the parameters which have to do with printer names. 130004c9c5dSGarance A Drosehn */ 131004c9c5dSGarance A Drosehn pp = &myprinter; 132004c9c5dSGarance A Drosehn generic_wrapup = NULL; 133004c9c5dSGarance A Drosehn generic_qselect = QSEL_UNKNOWN; 134004c9c5dSGarance A Drosehn cmdstatus = 0; 135004c9c5dSGarance A Drosehn /* this just needs to be a distinct value of type 'char *' */ 136004c9c5dSGarance A Drosehn if (generic_nullarg == NULL) 137004c9c5dSGarance A Drosehn generic_nullarg = strdup(""); 138004c9c5dSGarance A Drosehn 139004c9c5dSGarance A Drosehn /* call initialization routine, if there is one for this cmd */ 140004c9c5dSGarance A Drosehn if (initrtn != NULL) { 141004c9c5dSGarance A Drosehn generic_initerr = 0; 142004c9c5dSGarance A Drosehn (*initrtn)(argc, argv); 143004c9c5dSGarance A Drosehn if (generic_initerr) 144004c9c5dSGarance A Drosehn return; 145004c9c5dSGarance A Drosehn /* skip any initial arguments null-ified by initrtn */ 146004c9c5dSGarance A Drosehn targc = argc; 147004c9c5dSGarance A Drosehn targv = argv; 148004c9c5dSGarance A Drosehn while (--targc) { 149004c9c5dSGarance A Drosehn if (targv[1] != generic_nullarg) 150004c9c5dSGarance A Drosehn break; 151004c9c5dSGarance A Drosehn ++targv; 152004c9c5dSGarance A Drosehn } 153004c9c5dSGarance A Drosehn if (targv != argv) { 154004c9c5dSGarance A Drosehn targv[0] = argv[0]; /* copy the command-name */ 155004c9c5dSGarance A Drosehn argv = targv; 156004c9c5dSGarance A Drosehn argc = targc + 1; 157004c9c5dSGarance A Drosehn } 158004c9c5dSGarance A Drosehn } 159004c9c5dSGarance A Drosehn 1604a1a0dbeSGarrett Wollman if (argc == 2 && strcmp(argv[1], "all") == 0) { 161004c9c5dSGarance A Drosehn generic_qselect = QSEL_ALL; 162ba7a1ad7SGarance A Drosehn more = firstprinter(pp, &cmdstatus); 163ba7a1ad7SGarance A Drosehn if (cmdstatus) 1644a1a0dbeSGarrett Wollman goto looperr; 1654a1a0dbeSGarrett Wollman while (more) { 166ba7a1ad7SGarance A Drosehn (*specificrtn)(pp); 1674a1a0dbeSGarrett Wollman do { 168ba7a1ad7SGarance A Drosehn more = nextprinter(pp, &cmdstatus); 1694a1a0dbeSGarrett Wollman looperr: 170ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 1714a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 1724a1a0dbeSGarrett Wollman printf("warning: %s: unresolved " 1734a1a0dbeSGarrett Wollman "tc= reference(s) ", 1744a1a0dbeSGarrett Wollman pp->printer); 1754a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 1764a1a0dbeSGarrett Wollman break; 1774a1a0dbeSGarrett Wollman default: 1786d39e1b7SGarance A Drosehn fatal(pp, "%s", pcaperr(cmdstatus)); 1794a1a0dbeSGarrett Wollman } 180ba7a1ad7SGarance A Drosehn } while (more && cmdstatus); 1814a1a0dbeSGarrett Wollman } 182004c9c5dSGarance A Drosehn goto wrapup; 1834a1a0dbeSGarrett Wollman } 184004c9c5dSGarance A Drosehn 185004c9c5dSGarance A Drosehn generic_qselect = QSEL_BYNAME; /* specifically-named ptrs */ 1864a1a0dbeSGarrett Wollman while (--argc) { 1874a1a0dbeSGarrett Wollman ++argv; 188004c9c5dSGarance A Drosehn if (*argv == generic_nullarg) 189004c9c5dSGarance A Drosehn continue; 1904a1a0dbeSGarrett Wollman init_printer(pp); 191ba7a1ad7SGarance A Drosehn cmdstatus = getprintcap(*argv, pp); 192ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 1934a1a0dbeSGarrett Wollman default: 1946d39e1b7SGarance A Drosehn fatal(pp, "%s", pcaperr(cmdstatus)); 1954a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 1964a1a0dbeSGarrett Wollman printf("unknown printer %s\n", *argv); 1974a1a0dbeSGarrett Wollman continue; 1984a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 1994a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)\n", 2004a1a0dbeSGarrett Wollman *argv); 2014a1a0dbeSGarrett Wollman break; 2024a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 2034a1a0dbeSGarrett Wollman break; 2044a1a0dbeSGarrett Wollman } 205ba7a1ad7SGarance A Drosehn (*specificrtn)(pp); 2064a1a0dbeSGarrett Wollman } 207004c9c5dSGarance A Drosehn 208004c9c5dSGarance A Drosehn wrapup: 209004c9c5dSGarance A Drosehn if (generic_wrapup) { 210004c9c5dSGarance A Drosehn (*generic_wrapup)(cmdstatus); 211004c9c5dSGarance A Drosehn } 212004c9c5dSGarance A Drosehn 2134a1a0dbeSGarrett Wollman } 214dea673e9SRodney W. Grimes 215dea673e9SRodney W. Grimes /* 216dea673e9SRodney W. Grimes * kill an existing daemon and disable printing. 217dea673e9SRodney W. Grimes */ 218dea673e9SRodney W. Grimes void 219ba7a1ad7SGarance A Drosehn doabort(struct printer *pp) 220dea673e9SRodney W. Grimes { 2214a1a0dbeSGarrett Wollman abortpr(pp, 1); 222dea673e9SRodney W. Grimes } 223dea673e9SRodney W. Grimes 224dea673e9SRodney W. Grimes static void 225ba7a1ad7SGarance A Drosehn abortpr(struct printer *pp, int dis) 226dea673e9SRodney W. Grimes { 227dea673e9SRodney W. Grimes register FILE *fp; 228dea673e9SRodney W. Grimes struct stat stbuf; 229dea673e9SRodney W. Grimes int pid, fd; 2304a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 231dea673e9SRodney W. Grimes 2324a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 2334a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 234dea673e9SRodney W. Grimes 235dea673e9SRodney W. Grimes /* 236dea673e9SRodney W. Grimes * Turn on the owner execute bit of the lock file to disable printing. 237dea673e9SRodney W. Grimes */ 238dea673e9SRodney W. Grimes if (dis) { 239360d4ad5SWarner Losh seteuid(euid); 2404a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 2414a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 2424a1a0dbeSGarrett Wollman printf("\tcannot disable printing: %s\n", 2434a1a0dbeSGarrett Wollman strerror(errno)); 244dea673e9SRodney W. Grimes else { 2454a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 246dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 247dea673e9SRodney W. Grimes } 248dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 2494a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 2504a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 2514a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 2524a1a0dbeSGarrett Wollman strerror(errno)); 253dea673e9SRodney W. Grimes else { 254dea673e9SRodney W. Grimes (void) close(fd); 2554a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 256dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 257dea673e9SRodney W. Grimes printf("\tno daemon to abort\n"); 258dea673e9SRodney W. Grimes } 259360d4ad5SWarner Losh goto out; 260dea673e9SRodney W. Grimes } else { 261dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 262360d4ad5SWarner Losh goto out; 263dea673e9SRodney W. Grimes } 264dea673e9SRodney W. Grimes } 265dea673e9SRodney W. Grimes /* 266dea673e9SRodney W. Grimes * Kill the current daemon to stop printing now. 267dea673e9SRodney W. Grimes */ 2684a1a0dbeSGarrett Wollman if ((fp = fopen(lf, "r")) == NULL) { 269dea673e9SRodney W. Grimes printf("\tcannot open lock file\n"); 270360d4ad5SWarner Losh goto out; 271dea673e9SRodney W. Grimes } 272dea673e9SRodney W. Grimes if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 273dea673e9SRodney W. Grimes (void) fclose(fp); /* unlocks as well */ 274dea673e9SRodney W. Grimes printf("\tno daemon to abort\n"); 275360d4ad5SWarner Losh goto out; 276dea673e9SRodney W. Grimes } 277dea673e9SRodney W. Grimes (void) fclose(fp); 278360d4ad5SWarner Losh if (kill(pid = atoi(line), SIGTERM) < 0) { 279360d4ad5SWarner Losh if (errno == ESRCH) 280360d4ad5SWarner Losh printf("\tno daemon to abort\n"); 281dea673e9SRodney W. Grimes else 282360d4ad5SWarner Losh printf("\tWarning: daemon (pid %d) not killed\n", pid); 283360d4ad5SWarner Losh } else 284dea673e9SRodney W. Grimes printf("\tdaemon (pid %d) killed\n", pid); 285360d4ad5SWarner Losh out: 286360d4ad5SWarner Losh seteuid(uid); 287dea673e9SRodney W. Grimes } 288dea673e9SRodney W. Grimes 289dea673e9SRodney W. Grimes /* 290e8e715faSGarance A Drosehn * Kill the current daemon, to stop printing of the active job. 291e8e715faSGarance A Drosehn */ 292e8e715faSGarance A Drosehn static int 293e8e715faSGarance A Drosehn kill_qtask(const char *lf) 294e8e715faSGarance A Drosehn { 295e8e715faSGarance A Drosehn FILE *fp; 296e8e715faSGarance A Drosehn pid_t pid; 297e8e715faSGarance A Drosehn int errsav, killres, lockres, res; 298e8e715faSGarance A Drosehn 299e8e715faSGarance A Drosehn seteuid(euid); 300e8e715faSGarance A Drosehn fp = fopen(lf, "r"); 301e8e715faSGarance A Drosehn errsav = errno; 302e8e715faSGarance A Drosehn seteuid(uid); 303e8e715faSGarance A Drosehn res = KQT_NODAEMON; 304e8e715faSGarance A Drosehn if (fp == NULL) { 305e8e715faSGarance A Drosehn /* 306e8e715faSGarance A Drosehn * If there is no lock file, then there is no daemon to 307e8e715faSGarance A Drosehn * kill. Any other error return means there is some 308e8e715faSGarance A Drosehn * kind of problem with the lock file. 309e8e715faSGarance A Drosehn */ 310e8e715faSGarance A Drosehn if (errsav != ENOENT) 311e8e715faSGarance A Drosehn res = KQT_LFERROR; 312e8e715faSGarance A Drosehn goto killdone; 313e8e715faSGarance A Drosehn } 314e8e715faSGarance A Drosehn 315e8e715faSGarance A Drosehn /* If the lock file is empty, then there is no daemon to kill */ 316e8e715faSGarance A Drosehn if (getline(fp) == 0) 317e8e715faSGarance A Drosehn goto killdone; 318e8e715faSGarance A Drosehn 319e8e715faSGarance A Drosehn /* 320e8e715faSGarance A Drosehn * If the file can be locked without blocking, then there 321e8e715faSGarance A Drosehn * no daemon to kill, or we should not try to kill it. 322e8e715faSGarance A Drosehn * 323e8e715faSGarance A Drosehn * XXX - not sure I understand the reasoning behind this... 324e8e715faSGarance A Drosehn */ 325e8e715faSGarance A Drosehn lockres = flock(fileno(fp), LOCK_SH|LOCK_NB); 326e8e715faSGarance A Drosehn (void) fclose(fp); 327e8e715faSGarance A Drosehn if (lockres == 0) 328e8e715faSGarance A Drosehn goto killdone; 329e8e715faSGarance A Drosehn 330e8e715faSGarance A Drosehn pid = atoi(line); 331e8e715faSGarance A Drosehn if (pid < 0) { 332e8e715faSGarance A Drosehn /* 333e8e715faSGarance A Drosehn * If we got a negative pid, then the contents of the 334e8e715faSGarance A Drosehn * lock file is not valid. 335e8e715faSGarance A Drosehn */ 336e8e715faSGarance A Drosehn res = KQT_LFERROR; 337e8e715faSGarance A Drosehn goto killdone; 338e8e715faSGarance A Drosehn } 339e8e715faSGarance A Drosehn 340e8e715faSGarance A Drosehn seteuid(uid); 341e8e715faSGarance A Drosehn killres = kill(pid, SIGTERM); 342e8e715faSGarance A Drosehn errsav = errno; 343e8e715faSGarance A Drosehn seteuid(uid); 344e8e715faSGarance A Drosehn if (killres == 0) { 345e8e715faSGarance A Drosehn res = KQT_KILLOK; 346e8e715faSGarance A Drosehn printf("\tdaemon (pid %d) killed\n", pid); 347e8e715faSGarance A Drosehn } else if (errno == ESRCH) { 348e8e715faSGarance A Drosehn res = KQT_NODAEMON; 349e8e715faSGarance A Drosehn } else { 350e8e715faSGarance A Drosehn res = KQT_KILLFAIL; 351e8e715faSGarance A Drosehn printf("\tWarning: daemon (pid %d) not killed:\n", pid); 352e8e715faSGarance A Drosehn printf("\t %s\n", strerror(errsav)); 353e8e715faSGarance A Drosehn } 354e8e715faSGarance A Drosehn 355e8e715faSGarance A Drosehn killdone: 356e8e715faSGarance A Drosehn switch (res) { 357e8e715faSGarance A Drosehn case KQT_LFERROR: 358e8e715faSGarance A Drosehn printf("\tcannot open lock file: %s\n", 359e8e715faSGarance A Drosehn strerror(errsav)); 360e8e715faSGarance A Drosehn break; 361e8e715faSGarance A Drosehn case KQT_NODAEMON: 362e8e715faSGarance A Drosehn printf("\tno daemon to abort\n"); 363e8e715faSGarance A Drosehn break; 364e8e715faSGarance A Drosehn case KQT_KILLFAIL: 365e8e715faSGarance A Drosehn case KQT_KILLOK: 366e8e715faSGarance A Drosehn /* These two already printed messages to the user. */ 367e8e715faSGarance A Drosehn break; 368e8e715faSGarance A Drosehn default: 369e8e715faSGarance A Drosehn printf("\t<internal error in kill_qtask>\n"); 370e8e715faSGarance A Drosehn break; 371e8e715faSGarance A Drosehn } 372e8e715faSGarance A Drosehn 373e8e715faSGarance A Drosehn return (res); 374e8e715faSGarance A Drosehn } 375e8e715faSGarance A Drosehn 376e8e715faSGarance A Drosehn /* 377dea673e9SRodney W. Grimes * Write a message into the status file. 378dea673e9SRodney W. Grimes */ 379dea673e9SRodney W. Grimes static void 380ba7a1ad7SGarance A Drosehn upstat(struct printer *pp, const char *msg) 381dea673e9SRodney W. Grimes { 382dea673e9SRodney W. Grimes register int fd; 3835f87a7b6SWarner Losh char statfile[MAXPATHLEN]; 384dea673e9SRodney W. Grimes 3854a1a0dbeSGarrett Wollman status_file_name(pp, statfile, sizeof statfile); 386dea673e9SRodney W. Grimes umask(0); 3874a1a0dbeSGarrett Wollman fd = open(statfile, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 3884a1a0dbeSGarrett Wollman if (fd < 0) { 3894a1a0dbeSGarrett Wollman printf("\tcannot create status file: %s\n", strerror(errno)); 390dea673e9SRodney W. Grimes return; 391dea673e9SRodney W. Grimes } 392dea673e9SRodney W. Grimes (void) ftruncate(fd, 0); 393dea673e9SRodney W. Grimes if (msg == (char *)NULL) 394dea673e9SRodney W. Grimes (void) write(fd, "\n", 1); 395dea673e9SRodney W. Grimes else 396dea673e9SRodney W. Grimes (void) write(fd, msg, strlen(msg)); 397dea673e9SRodney W. Grimes (void) close(fd); 398dea673e9SRodney W. Grimes } 399dea673e9SRodney W. Grimes 400004c9c5dSGarance A Drosehn /* 401e8e715faSGarance A Drosehn * kill an existing daemon and disable printing. 402e8e715faSGarance A Drosehn */ 403e8e715faSGarance A Drosehn void 404e8e715faSGarance A Drosehn abort_q(struct printer *pp) 405e8e715faSGarance A Drosehn { 406e8e715faSGarance A Drosehn int killres, setres; 407e8e715faSGarance A Drosehn char lf[MAXPATHLEN]; 408e8e715faSGarance A Drosehn 409e8e715faSGarance A Drosehn lock_file_name(pp, lf, sizeof lf); 410e8e715faSGarance A Drosehn printf("%s:\n", pp->printer); 411e8e715faSGarance A Drosehn 412e8e715faSGarance A Drosehn /* 413e8e715faSGarance A Drosehn * Turn on the owner execute bit of the lock file to disable printing. 414e8e715faSGarance A Drosehn */ 415e8e715faSGarance A Drosehn setres = set_qstate(SQS_STOPP, lf); 416e8e715faSGarance A Drosehn 417e8e715faSGarance A Drosehn /* 418e8e715faSGarance A Drosehn * If set_qstate found that there already was a lock file, then 419e8e715faSGarance A Drosehn * call a routine which will read that lock file and kill the 420e8e715faSGarance A Drosehn * lpd-process which is listed in that lock file. If the lock 421e8e715faSGarance A Drosehn * file did not exist, then either there is no daemon running 422e8e715faSGarance A Drosehn * for this queue, or there is one running but *it* could not 423e8e715faSGarance A Drosehn * write a lock file (which means we can not determine the 424e8e715faSGarance A Drosehn * process id of that lpd-process). 425e8e715faSGarance A Drosehn */ 426e8e715faSGarance A Drosehn switch (setres) { 427e8e715faSGarance A Drosehn case SQS_CHGOK: 428e8e715faSGarance A Drosehn case SQS_CHGFAIL: 429e8e715faSGarance A Drosehn /* Kill the process */ 430e8e715faSGarance A Drosehn killres = kill_qtask(lf); 431e8e715faSGarance A Drosehn break; 432e8e715faSGarance A Drosehn case SQS_CREOK: 433e8e715faSGarance A Drosehn case SQS_CREFAIL: 434e8e715faSGarance A Drosehn printf("\tno daemon to abort\n"); 435e8e715faSGarance A Drosehn break; 436e8e715faSGarance A Drosehn case SQS_STATFAIL: 437e8e715faSGarance A Drosehn printf("\tassuming no daemon to abort\n"); 438e8e715faSGarance A Drosehn break; 439e8e715faSGarance A Drosehn default: 440e8e715faSGarance A Drosehn printf("\t<unexpected result (%d) from set_qstate>\n", 441e8e715faSGarance A Drosehn setres); 442e8e715faSGarance A Drosehn break; 443e8e715faSGarance A Drosehn } 444e8e715faSGarance A Drosehn 445e8e715faSGarance A Drosehn if (setres >= 0) { 446e8e715faSGarance A Drosehn seteuid(euid); 447e8e715faSGarance A Drosehn upstat(pp, "printing disabled\n"); 448e8e715faSGarance A Drosehn seteuid(uid); 449e8e715faSGarance A Drosehn } 450e8e715faSGarance A Drosehn } 451e8e715faSGarance A Drosehn 452e8e715faSGarance A Drosehn /* 453004c9c5dSGarance A Drosehn * "global" variables for all the routines related to 'clean' and 'tclean' 454004c9c5dSGarance A Drosehn */ 455004c9c5dSGarance A Drosehn static time_t cln_now; /* current time */ 456004c9c5dSGarance A Drosehn static double cln_minage; /* minimum age before file is removed */ 457004c9c5dSGarance A Drosehn static long cln_sizecnt; /* amount of space freed up */ 458004c9c5dSGarance A Drosehn static int cln_debug; /* print extra debugging msgs */ 459004c9c5dSGarance A Drosehn static int cln_filecnt; /* number of files destroyed */ 460004c9c5dSGarance A Drosehn static int cln_foundcore; /* found a core file! */ 461004c9c5dSGarance A Drosehn static int cln_queuecnt; /* number of queues checked */ 462004c9c5dSGarance A Drosehn static int cln_testonly; /* remove-files vs just-print-info */ 463004c9c5dSGarance A Drosehn 464dea673e9SRodney W. Grimes static int 465ba7a1ad7SGarance A Drosehn doselect(struct dirent *d) 466dea673e9SRodney W. Grimes { 467dea673e9SRodney W. Grimes int c = d->d_name[0]; 468dea673e9SRodney W. Grimes 4691fd731faSGarance A Drosehn if ((c == 'c' || c == 'd' || c == 'r' || c == 't') && 4701fd731faSGarance A Drosehn d->d_name[1] == 'f') 471004c9c5dSGarance A Drosehn return 1; 472004c9c5dSGarance A Drosehn if (c == 'c') { 473004c9c5dSGarance A Drosehn if (!strcmp(d->d_name, "core")) 474004c9c5dSGarance A Drosehn cln_foundcore = 1; 475004c9c5dSGarance A Drosehn } 476004c9c5dSGarance A Drosehn if (c == 'e') { 477004c9c5dSGarance A Drosehn if (!strncmp(d->d_name, "errs.", 5)) 478004c9c5dSGarance A Drosehn return 1; 479004c9c5dSGarance A Drosehn } 480004c9c5dSGarance A Drosehn return 0; 481dea673e9SRodney W. Grimes } 482dea673e9SRodney W. Grimes 483dea673e9SRodney W. Grimes /* 484ceeaedd3SGarance A Drosehn * Comparison routine that clean_q() uses for scandir. 485ceeaedd3SGarance A Drosehn * 486ceeaedd3SGarance A Drosehn * The purpose of this sort is to have all `df' files end up immediately 4871fd731faSGarance A Drosehn * after the matching `cf' file. For files matching `cf', `df', `rf', or 4881fd731faSGarance A Drosehn * `tf', it sorts by job number and machine, then by `cf', `df', `rf', or 4891fd731faSGarance A Drosehn * `tf', and then by the sequence letter (which is A-Z, or a-z). This 4901fd731faSGarance A Drosehn * routine may also see filenames which do not start with `cf', `df', `rf', 4911fd731faSGarance A Drosehn * or `tf' (such as `errs.*'), and those are simply sorted by the full 4921fd731faSGarance A Drosehn * filename. 4931fd731faSGarance A Drosehn * 4941fd731faSGarance A Drosehn * XXX 4951fd731faSGarance A Drosehn * This assumes that all control files start with `cfA*', and it turns 4961fd731faSGarance A Drosehn * out there are a few implementations of lpr which will create `cfB*' 4971fd731faSGarance A Drosehn * filenames (they will have datafile names which start with `dfB*'). 498dea673e9SRodney W. Grimes */ 499dea673e9SRodney W. Grimes static int 500ba7a1ad7SGarance A Drosehn sortq(const void *a, const void *b) 501dea673e9SRodney W. Grimes { 502ceeaedd3SGarance A Drosehn const int a_lt_b = -1, a_gt_b = 1, cat_other = 10; 503ceeaedd3SGarance A Drosehn const char *fname_a, *fname_b, *jnum_a, *jnum_b; 504ceeaedd3SGarance A Drosehn int cat_a, cat_b, ch, res, seq_a, seq_b; 505dea673e9SRodney W. Grimes 506f0baf665SGarance A Drosehn fname_a = (*(const struct dirent * const *)a)->d_name; 507f0baf665SGarance A Drosehn fname_b = (*(const struct dirent * const *)b)->d_name; 508ceeaedd3SGarance A Drosehn 509ceeaedd3SGarance A Drosehn /* 510ceeaedd3SGarance A Drosehn * First separate filenames into cagatories. Catagories are 5111fd731faSGarance A Drosehn * legitimate `cf', `df', `rf' & `tf' filenames, and "other" - in 5121fd731faSGarance A Drosehn * that order. It is critical that the mapping be exactly the 5131fd731faSGarance A Drosehn * same for 'a' vs 'b', so define a macro for the job. 514ceeaedd3SGarance A Drosehn * 515ceeaedd3SGarance A Drosehn * [aside: the standard `cf' file has the jobnumber start in 516ceeaedd3SGarance A Drosehn * position 4, but some implementations have that as an extra 517ceeaedd3SGarance A Drosehn * file-sequence letter, and start the job number in position 5.] 518ceeaedd3SGarance A Drosehn */ 519ceeaedd3SGarance A Drosehn #define MAP_TO_CAT(fname_X,cat_X,jnum_X,seq_X) do { \ 520ceeaedd3SGarance A Drosehn cat_X = cat_other; \ 521ceeaedd3SGarance A Drosehn ch = *(fname_X + 2); \ 522ceeaedd3SGarance A Drosehn jnum_X = fname_X + 3; \ 5234f7f8234SGarance A Drosehn seq_X = 0; \ 524ceeaedd3SGarance A Drosehn if ((*(fname_X + 1) == 'f') && (isalpha(ch))) { \ 525ceeaedd3SGarance A Drosehn seq_X = ch; \ 526ceeaedd3SGarance A Drosehn if (*fname_X == 'c') \ 527ceeaedd3SGarance A Drosehn cat_X = 1; \ 528ceeaedd3SGarance A Drosehn else if (*fname_X == 'd') \ 529ceeaedd3SGarance A Drosehn cat_X = 2; \ 5301fd731faSGarance A Drosehn else if (*fname_X == 'r') \ 531ceeaedd3SGarance A Drosehn cat_X = 3; \ 5321fd731faSGarance A Drosehn else if (*fname_X == 't') \ 5331fd731faSGarance A Drosehn cat_X = 4; \ 534ceeaedd3SGarance A Drosehn if (cat_X != cat_other) { \ 535ceeaedd3SGarance A Drosehn ch = *jnum_X; \ 536ceeaedd3SGarance A Drosehn if (!isdigit(ch)) { \ 537ceeaedd3SGarance A Drosehn if (isalpha(ch)) { \ 538ceeaedd3SGarance A Drosehn jnum_X++; \ 539ceeaedd3SGarance A Drosehn ch = *jnum_X; \ 540ceeaedd3SGarance A Drosehn seq_X = (seq_X << 8) + ch; \ 541ceeaedd3SGarance A Drosehn } \ 542ceeaedd3SGarance A Drosehn if (!isdigit(ch)) \ 543ceeaedd3SGarance A Drosehn cat_X = cat_other; \ 544ceeaedd3SGarance A Drosehn } \ 545ceeaedd3SGarance A Drosehn } \ 546ceeaedd3SGarance A Drosehn } \ 547ceeaedd3SGarance A Drosehn } while (0) 548ceeaedd3SGarance A Drosehn 549ceeaedd3SGarance A Drosehn MAP_TO_CAT(fname_a, cat_a, jnum_a, seq_a); 550ceeaedd3SGarance A Drosehn MAP_TO_CAT(fname_b, cat_b, jnum_b, seq_b); 551ceeaedd3SGarance A Drosehn 552ceeaedd3SGarance A Drosehn #undef MAP_TO_CAT 553ceeaedd3SGarance A Drosehn 554ceeaedd3SGarance A Drosehn /* First handle all cases which have "other" files */ 555ceeaedd3SGarance A Drosehn if ((cat_a >= cat_other) || (cat_b >= cat_other)) { 556ceeaedd3SGarance A Drosehn /* for two "other" files, just compare the full name */ 557ceeaedd3SGarance A Drosehn if (cat_a == cat_b) 558ceeaedd3SGarance A Drosehn res = strcmp(fname_a, fname_b); 559ceeaedd3SGarance A Drosehn else if (cat_a < cat_b) 560ceeaedd3SGarance A Drosehn res = a_lt_b; 561ceeaedd3SGarance A Drosehn else 562ceeaedd3SGarance A Drosehn res = a_gt_b; 563ceeaedd3SGarance A Drosehn goto have_res; 564ceeaedd3SGarance A Drosehn } 565ceeaedd3SGarance A Drosehn 566ceeaedd3SGarance A Drosehn /* 5671fd731faSGarance A Drosehn * At this point, we know both files are legitimate `cf', `df', `rf', 568ceeaedd3SGarance A Drosehn * or `tf' files. Compare them by job-number and machine name. 569ceeaedd3SGarance A Drosehn */ 570ceeaedd3SGarance A Drosehn res = strcmp(jnum_a, jnum_b); 571ceeaedd3SGarance A Drosehn if (res != 0) 572ceeaedd3SGarance A Drosehn goto have_res; 573ceeaedd3SGarance A Drosehn 574ceeaedd3SGarance A Drosehn /* 575ceeaedd3SGarance A Drosehn * We have two files which belong to the same job. Sort based 576ceeaedd3SGarance A Drosehn * on the catagory of file (`c' before `d', etc). 577ceeaedd3SGarance A Drosehn */ 578ceeaedd3SGarance A Drosehn if (cat_a < cat_b) { 579ceeaedd3SGarance A Drosehn res = a_lt_b; 580ceeaedd3SGarance A Drosehn goto have_res; 581ceeaedd3SGarance A Drosehn } else if (cat_a > cat_b) { 582ceeaedd3SGarance A Drosehn res = a_gt_b; 583ceeaedd3SGarance A Drosehn goto have_res; 584ceeaedd3SGarance A Drosehn } 585ceeaedd3SGarance A Drosehn 586ceeaedd3SGarance A Drosehn /* 587ceeaedd3SGarance A Drosehn * Two files in the same catagory for a single job. Sort based 588ceeaedd3SGarance A Drosehn * on the sequence letter(s). (usually `A' thru `Z', etc). 589ceeaedd3SGarance A Drosehn */ 590ceeaedd3SGarance A Drosehn if (seq_a < seq_b) { 591ceeaedd3SGarance A Drosehn res = a_lt_b; 592ceeaedd3SGarance A Drosehn goto have_res; 593ceeaedd3SGarance A Drosehn } else if (seq_a > seq_b) { 594ceeaedd3SGarance A Drosehn res = a_gt_b; 595ceeaedd3SGarance A Drosehn goto have_res; 596ceeaedd3SGarance A Drosehn } 597ceeaedd3SGarance A Drosehn 598ceeaedd3SGarance A Drosehn /* 599ceeaedd3SGarance A Drosehn * Given that the filenames in a directory are unique, this SHOULD 600ceeaedd3SGarance A Drosehn * never happen (unless there are logic errors in this routine). 601ceeaedd3SGarance A Drosehn * But if it does happen, we must return "is equal" or the caller 602ceeaedd3SGarance A Drosehn * might see inconsistent results in the sorting order, and that 603ceeaedd3SGarance A Drosehn * can trigger other problems. 604ceeaedd3SGarance A Drosehn */ 605ceeaedd3SGarance A Drosehn printf("\t*** Error in sortq: %s == %s !\n", fname_a, fname_b); 606ceeaedd3SGarance A Drosehn printf("\t*** cat %d == %d ; seq = %d %d\n", cat_a, cat_b, 607ceeaedd3SGarance A Drosehn seq_a, seq_b); 608ceeaedd3SGarance A Drosehn res = 0; 609ceeaedd3SGarance A Drosehn 610ceeaedd3SGarance A Drosehn have_res: 611ceeaedd3SGarance A Drosehn return res; 612dea673e9SRodney W. Grimes } 613dea673e9SRodney W. Grimes 614dea673e9SRodney W. Grimes /* 6154a1a0dbeSGarrett Wollman * Remove all spool files and temporaries from the spooling area. 6164a1a0dbeSGarrett Wollman * Or, perhaps: 617dea673e9SRodney W. Grimes * Remove incomplete jobs from spooling area. 618dea673e9SRodney W. Grimes */ 619dea673e9SRodney W. Grimes 620004c9c5dSGarance A Drosehn void 621004c9c5dSGarance A Drosehn init_clean(int argc, char *argv[]) 622004c9c5dSGarance A Drosehn { 623004c9c5dSGarance A Drosehn 624004c9c5dSGarance A Drosehn /* init some fields before 'clean' is called for each queue */ 625004c9c5dSGarance A Drosehn cln_queuecnt = 0; 626004c9c5dSGarance A Drosehn cln_now = time(NULL); 627004c9c5dSGarance A Drosehn cln_minage = 3600.0; /* only delete files >1h old */ 628004c9c5dSGarance A Drosehn cln_filecnt = 0; 629004c9c5dSGarance A Drosehn cln_sizecnt = 0; 630004c9c5dSGarance A Drosehn cln_debug = 0; 631004c9c5dSGarance A Drosehn cln_testonly = 0; 632004c9c5dSGarance A Drosehn generic_wrapup = &wrapup_clean; 633004c9c5dSGarance A Drosehn 634004c9c5dSGarance A Drosehn /* see if there are any options specified before the ptr list */ 635004c9c5dSGarance A Drosehn while (--argc) { 636004c9c5dSGarance A Drosehn ++argv; 637004c9c5dSGarance A Drosehn if (**argv != '-') 638004c9c5dSGarance A Drosehn break; 639004c9c5dSGarance A Drosehn if (strcmp(*argv, "-d") == 0) { 640004c9c5dSGarance A Drosehn /* just an example of an option... */ 641ceeaedd3SGarance A Drosehn cln_debug++; 642004c9c5dSGarance A Drosehn *argv = generic_nullarg; /* "erase" it */ 643004c9c5dSGarance A Drosehn } else { 644004c9c5dSGarance A Drosehn printf("Invalid option '%s'\n", *argv); 645004c9c5dSGarance A Drosehn generic_initerr = 1; 646004c9c5dSGarance A Drosehn } 647004c9c5dSGarance A Drosehn } 648004c9c5dSGarance A Drosehn 649004c9c5dSGarance A Drosehn return; 650004c9c5dSGarance A Drosehn } 651004c9c5dSGarance A Drosehn 652004c9c5dSGarance A Drosehn void 653004c9c5dSGarance A Drosehn init_tclean(int argc, char *argv[]) 654004c9c5dSGarance A Drosehn { 655004c9c5dSGarance A Drosehn 656004c9c5dSGarance A Drosehn /* only difference between 'clean' and 'tclean' is one value */ 657004c9c5dSGarance A Drosehn /* (...and the fact that 'clean' is priv and 'tclean' is not) */ 658004c9c5dSGarance A Drosehn init_clean(argc, argv); 659004c9c5dSGarance A Drosehn cln_testonly = 1; 660004c9c5dSGarance A Drosehn 661004c9c5dSGarance A Drosehn return; 662004c9c5dSGarance A Drosehn } 663004c9c5dSGarance A Drosehn 664004c9c5dSGarance A Drosehn void 665004c9c5dSGarance A Drosehn clean_q(struct printer *pp) 666004c9c5dSGarance A Drosehn { 667004c9c5dSGarance A Drosehn char *cp, *cp1, *lp; 668004c9c5dSGarance A Drosehn struct dirent **queue; 669004c9c5dSGarance A Drosehn size_t linerem; 670004c9c5dSGarance A Drosehn int didhead, i, n, nitems, rmcp; 671004c9c5dSGarance A Drosehn 672004c9c5dSGarance A Drosehn cln_queuecnt++; 673004c9c5dSGarance A Drosehn 674004c9c5dSGarance A Drosehn didhead = 0; 675004c9c5dSGarance A Drosehn if (generic_qselect == QSEL_BYNAME) { 6764a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 677004c9c5dSGarance A Drosehn didhead = 1; 678004c9c5dSGarance A Drosehn } 679dea673e9SRodney W. Grimes 6804a1a0dbeSGarrett Wollman lp = line; 6814a1a0dbeSGarrett Wollman cp = pp->spool_dir; 6824a1a0dbeSGarrett Wollman while (lp < &line[sizeof(line) - 1]) { 6834a1a0dbeSGarrett Wollman if ((*lp++ = *cp++) == 0) 6844a1a0dbeSGarrett Wollman break; 6854a1a0dbeSGarrett Wollman } 686dea673e9SRodney W. Grimes lp[-1] = '/'; 687004c9c5dSGarance A Drosehn linerem = sizeof(line) - (lp - line); 688dea673e9SRodney W. Grimes 689004c9c5dSGarance A Drosehn cln_foundcore = 0; 690360d4ad5SWarner Losh seteuid(euid); 6914a1a0dbeSGarrett Wollman nitems = scandir(pp->spool_dir, &queue, doselect, sortq); 692360d4ad5SWarner Losh seteuid(uid); 693dea673e9SRodney W. Grimes if (nitems < 0) { 694004c9c5dSGarance A Drosehn if (!didhead) { 695004c9c5dSGarance A Drosehn printf("%s:\n", pp->printer); 696004c9c5dSGarance A Drosehn didhead = 1; 697004c9c5dSGarance A Drosehn } 698dea673e9SRodney W. Grimes printf("\tcannot examine spool directory\n"); 699dea673e9SRodney W. Grimes return; 700dea673e9SRodney W. Grimes } 701004c9c5dSGarance A Drosehn if (cln_foundcore) { 702004c9c5dSGarance A Drosehn if (!didhead) { 703004c9c5dSGarance A Drosehn printf("%s:\n", pp->printer); 704004c9c5dSGarance A Drosehn didhead = 1; 705004c9c5dSGarance A Drosehn } 706004c9c5dSGarance A Drosehn printf("\t** found a core file in %s !\n", pp->spool_dir); 707004c9c5dSGarance A Drosehn } 708dea673e9SRodney W. Grimes if (nitems == 0) 709dea673e9SRodney W. Grimes return; 710004c9c5dSGarance A Drosehn if (!didhead) 711004c9c5dSGarance A Drosehn printf("%s:\n", pp->printer); 712ceeaedd3SGarance A Drosehn if (cln_debug) { 713ceeaedd3SGarance A Drosehn printf("\t** ----- Sorted list of files being checked:\n"); 714ceeaedd3SGarance A Drosehn i = 0; 715ceeaedd3SGarance A Drosehn do { 716ceeaedd3SGarance A Drosehn cp = queue[i]->d_name; 717ceeaedd3SGarance A Drosehn printf("\t** [%3d] = %s\n", i, cp); 718ceeaedd3SGarance A Drosehn } while (++i < nitems); 719ceeaedd3SGarance A Drosehn printf("\t** ----- end of sorted list\n"); 720ceeaedd3SGarance A Drosehn } 721dea673e9SRodney W. Grimes i = 0; 722dea673e9SRodney W. Grimes do { 723dea673e9SRodney W. Grimes cp = queue[i]->d_name; 724004c9c5dSGarance A Drosehn rmcp = 0; 725dea673e9SRodney W. Grimes if (*cp == 'c') { 726004c9c5dSGarance A Drosehn /* 727004c9c5dSGarance A Drosehn * A control file. Look for matching data-files. 728004c9c5dSGarance A Drosehn */ 729004c9c5dSGarance A Drosehn /* XXX 730004c9c5dSGarance A Drosehn * Note the logic here assumes that the hostname 731004c9c5dSGarance A Drosehn * part of cf-filenames match the hostname part 732004c9c5dSGarance A Drosehn * in df-filenames, and that is not necessarily 733004c9c5dSGarance A Drosehn * true (eg: for multi-homed hosts). This needs 734004c9c5dSGarance A Drosehn * some further thought... 735004c9c5dSGarance A Drosehn */ 736dea673e9SRodney W. Grimes n = 0; 737dea673e9SRodney W. Grimes while (i + 1 < nitems) { 738dea673e9SRodney W. Grimes cp1 = queue[i + 1]->d_name; 739dea673e9SRodney W. Grimes if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 740dea673e9SRodney W. Grimes break; 741dea673e9SRodney W. Grimes i++; 742dea673e9SRodney W. Grimes n++; 743dea673e9SRodney W. Grimes } 744dea673e9SRodney W. Grimes if (n == 0) { 745004c9c5dSGarance A Drosehn rmcp = 1; 746dea673e9SRodney W. Grimes } 747004c9c5dSGarance A Drosehn } else if (*cp == 'e') { 748004c9c5dSGarance A Drosehn /* 749004c9c5dSGarance A Drosehn * Must be an errrs or email temp file. 750004c9c5dSGarance A Drosehn */ 751004c9c5dSGarance A Drosehn rmcp = 1; 752dea673e9SRodney W. Grimes } else { 753dea673e9SRodney W. Grimes /* 754dea673e9SRodney W. Grimes * Must be a df with no cf (otherwise, it would have 7551fd731faSGarance A Drosehn * been skipped above) or an rf or tf file (which can 7561fd731faSGarance A Drosehn * always be removed if it is old enough). 757dea673e9SRodney W. Grimes */ 758004c9c5dSGarance A Drosehn rmcp = 1; 759004c9c5dSGarance A Drosehn } 760004c9c5dSGarance A Drosehn if (rmcp) { 761004c9c5dSGarance A Drosehn if (strlen(cp) >= linerem) { 762004c9c5dSGarance A Drosehn printf("\t** internal error: 'line' overflow!\n"); 763004c9c5dSGarance A Drosehn printf("\t** spooldir = %s\n", pp->spool_dir); 764004c9c5dSGarance A Drosehn printf("\t** cp = %s\n", cp); 765004c9c5dSGarance A Drosehn return; 766004c9c5dSGarance A Drosehn } 767004c9c5dSGarance A Drosehn strlcpy(lp, cp, linerem); 768dea673e9SRodney W. Grimes unlinkf(line); 769dea673e9SRodney W. Grimes } 770dea673e9SRodney W. Grimes } while (++i < nitems); 771dea673e9SRodney W. Grimes } 772dea673e9SRodney W. Grimes 773dea673e9SRodney W. Grimes static void 774004c9c5dSGarance A Drosehn wrapup_clean(int laststatus __unused) 775004c9c5dSGarance A Drosehn { 776004c9c5dSGarance A Drosehn 777004c9c5dSGarance A Drosehn printf("Checked %d queues, and ", cln_queuecnt); 778004c9c5dSGarance A Drosehn if (cln_filecnt < 1) { 779004c9c5dSGarance A Drosehn printf("no cruft was found\n"); 780004c9c5dSGarance A Drosehn return; 781004c9c5dSGarance A Drosehn } 782004c9c5dSGarance A Drosehn if (cln_testonly) { 783004c9c5dSGarance A Drosehn printf("would have "); 784004c9c5dSGarance A Drosehn } 785004c9c5dSGarance A Drosehn printf("removed %d files (%ld bytes).\n", cln_filecnt, cln_sizecnt); 786004c9c5dSGarance A Drosehn } 787004c9c5dSGarance A Drosehn 788004c9c5dSGarance A Drosehn static void 789ba7a1ad7SGarance A Drosehn unlinkf(char *name) 790dea673e9SRodney W. Grimes { 791004c9c5dSGarance A Drosehn struct stat stbuf; 792004c9c5dSGarance A Drosehn double agemod, agestat; 793004c9c5dSGarance A Drosehn int res; 794004c9c5dSGarance A Drosehn char linkbuf[BUFSIZ]; 795004c9c5dSGarance A Drosehn 796004c9c5dSGarance A Drosehn /* 797004c9c5dSGarance A Drosehn * We have to use lstat() instead of stat(), in case this is a df* 798004c9c5dSGarance A Drosehn * "file" which is really a symlink due to 'lpr -s' processing. In 799004c9c5dSGarance A Drosehn * that case, we need to check the last-mod time of the symlink, and 800004c9c5dSGarance A Drosehn * not the file that the symlink is pointed at. 801004c9c5dSGarance A Drosehn */ 802360d4ad5SWarner Losh seteuid(euid); 803004c9c5dSGarance A Drosehn res = lstat(name, &stbuf); 804004c9c5dSGarance A Drosehn seteuid(uid); 805004c9c5dSGarance A Drosehn if (res < 0) { 806004c9c5dSGarance A Drosehn printf("\terror return from stat(%s):\n", name); 807004c9c5dSGarance A Drosehn printf("\t %s\n", strerror(errno)); 808004c9c5dSGarance A Drosehn return; 809004c9c5dSGarance A Drosehn } 810004c9c5dSGarance A Drosehn 811004c9c5dSGarance A Drosehn agemod = difftime(cln_now, stbuf.st_mtime); 812004c9c5dSGarance A Drosehn agestat = difftime(cln_now, stbuf.st_ctime); 813ceeaedd3SGarance A Drosehn if (cln_debug > 1) { 814004c9c5dSGarance A Drosehn /* this debugging-aid probably is not needed any more... */ 815004c9c5dSGarance A Drosehn printf("\t\t modify age=%g secs, stat age=%g secs\n", 816004c9c5dSGarance A Drosehn agemod, agestat); 817004c9c5dSGarance A Drosehn } 818004c9c5dSGarance A Drosehn if ((agemod <= cln_minage) && (agestat <= cln_minage)) 819004c9c5dSGarance A Drosehn return; 820004c9c5dSGarance A Drosehn 821004c9c5dSGarance A Drosehn /* 822004c9c5dSGarance A Drosehn * if this file is a symlink, then find out the target of the 823004c9c5dSGarance A Drosehn * symlink before unlink-ing the file itself 824004c9c5dSGarance A Drosehn */ 825004c9c5dSGarance A Drosehn if (S_ISLNK(stbuf.st_mode)) { 826004c9c5dSGarance A Drosehn seteuid(euid); 827004c9c5dSGarance A Drosehn res = readlink(name, linkbuf, sizeof(linkbuf)); 828004c9c5dSGarance A Drosehn seteuid(uid); 829004c9c5dSGarance A Drosehn if (res < 0) { 830004c9c5dSGarance A Drosehn printf("\terror return from readlink(%s):\n", name); 831004c9c5dSGarance A Drosehn printf("\t %s\n", strerror(errno)); 832004c9c5dSGarance A Drosehn return; 833004c9c5dSGarance A Drosehn } 834004c9c5dSGarance A Drosehn if (res == sizeof(linkbuf)) 835004c9c5dSGarance A Drosehn res--; 836004c9c5dSGarance A Drosehn linkbuf[res] = '\0'; 837004c9c5dSGarance A Drosehn } 838004c9c5dSGarance A Drosehn 839004c9c5dSGarance A Drosehn cln_filecnt++; 840004c9c5dSGarance A Drosehn cln_sizecnt += stbuf.st_size; 841004c9c5dSGarance A Drosehn 842004c9c5dSGarance A Drosehn if (cln_testonly) { 843004c9c5dSGarance A Drosehn printf("\twould remove %s\n", name); 844004c9c5dSGarance A Drosehn if (S_ISLNK(stbuf.st_mode)) { 845004c9c5dSGarance A Drosehn printf("\t (which is a symlink to %s)\n", linkbuf); 846004c9c5dSGarance A Drosehn } 847004c9c5dSGarance A Drosehn } else { 848004c9c5dSGarance A Drosehn seteuid(euid); 849004c9c5dSGarance A Drosehn res = unlink(name); 850004c9c5dSGarance A Drosehn seteuid(uid); 851004c9c5dSGarance A Drosehn if (res < 0) 852004c9c5dSGarance A Drosehn printf("\tcannot remove %s (!)\n", name); 853dea673e9SRodney W. Grimes else 854dea673e9SRodney W. Grimes printf("\tremoved %s\n", name); 855004c9c5dSGarance A Drosehn /* XXX 856004c9c5dSGarance A Drosehn * Note that for a df* file, this code should also check to see 857004c9c5dSGarance A Drosehn * if it is a symlink to some other file, and if the original 858004c9c5dSGarance A Drosehn * lpr command included '-r' ("remove file"). Of course, this 859004c9c5dSGarance A Drosehn * code would not be removing the df* file unless there was no 860004c9c5dSGarance A Drosehn * matching cf* file, and without the cf* file it is currently 861004c9c5dSGarance A Drosehn * impossible to determine if '-r' had been specified... 862004c9c5dSGarance A Drosehn * 863004c9c5dSGarance A Drosehn * As a result of this quandry, we may be leaving behind a 864004c9c5dSGarance A Drosehn * user's file that was supposed to have been removed after 865004c9c5dSGarance A Drosehn * being printed. This may effect services such as CAP or 866004c9c5dSGarance A Drosehn * samba, if they were configured to use 'lpr -r', and if 867004c9c5dSGarance A Drosehn * datafiles are not being properly removed. 868004c9c5dSGarance A Drosehn */ 869004c9c5dSGarance A Drosehn if (S_ISLNK(stbuf.st_mode)) { 870004c9c5dSGarance A Drosehn printf("\t (which was a symlink to %s)\n", linkbuf); 871004c9c5dSGarance A Drosehn } 872004c9c5dSGarance A Drosehn } 873dea673e9SRodney W. Grimes } 874dea673e9SRodney W. Grimes 875dea673e9SRodney W. Grimes /* 876dea673e9SRodney W. Grimes * Enable queuing to the printer (allow lpr's). 877dea673e9SRodney W. Grimes */ 878dea673e9SRodney W. Grimes void 879ba7a1ad7SGarance A Drosehn enable(struct printer *pp) 880dea673e9SRodney W. Grimes { 881dea673e9SRodney W. Grimes struct stat stbuf; 8824a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 883dea673e9SRodney W. Grimes 8844a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 8854a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 886dea673e9SRodney W. Grimes 887dea673e9SRodney W. Grimes /* 888dea673e9SRodney W. Grimes * Turn off the group execute bit of the lock file to enable queuing. 889dea673e9SRodney W. Grimes */ 890360d4ad5SWarner Losh seteuid(euid); 8914a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 8924a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode & ~LFM_QUEUE_DIS) < 0) 893dea673e9SRodney W. Grimes printf("\tcannot enable queuing\n"); 894dea673e9SRodney W. Grimes else 895dea673e9SRodney W. Grimes printf("\tqueuing enabled\n"); 896dea673e9SRodney W. Grimes } 897360d4ad5SWarner Losh seteuid(uid); 898dea673e9SRodney W. Grimes } 899dea673e9SRodney W. Grimes 900dea673e9SRodney W. Grimes /* 901e8e715faSGarance A Drosehn * Enable queuing to the printer (allow lpr to add new jobs to the queue). 902e8e715faSGarance A Drosehn */ 903e8e715faSGarance A Drosehn void 904e8e715faSGarance A Drosehn enable_q(struct printer *pp) 905e8e715faSGarance A Drosehn { 906e8e715faSGarance A Drosehn int setres; 907e8e715faSGarance A Drosehn char lf[MAXPATHLEN]; 908e8e715faSGarance A Drosehn 909e8e715faSGarance A Drosehn lock_file_name(pp, lf, sizeof lf); 910e8e715faSGarance A Drosehn printf("%s:\n", pp->printer); 911e8e715faSGarance A Drosehn 912e8e715faSGarance A Drosehn setres = set_qstate(SQS_ENABLEQ, lf); 913e8e715faSGarance A Drosehn } 914e8e715faSGarance A Drosehn 915e8e715faSGarance A Drosehn /* 916dea673e9SRodney W. Grimes * Disable queuing. 917dea673e9SRodney W. Grimes */ 918dea673e9SRodney W. Grimes void 919ba7a1ad7SGarance A Drosehn disable(struct printer *pp) 920dea673e9SRodney W. Grimes { 921dea673e9SRodney W. Grimes register int fd; 922dea673e9SRodney W. Grimes struct stat stbuf; 9234a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 924dea673e9SRodney W. Grimes 9254a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 9264a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 927dea673e9SRodney W. Grimes /* 928dea673e9SRodney W. Grimes * Turn on the group execute bit of the lock file to disable queuing. 929dea673e9SRodney W. Grimes */ 930360d4ad5SWarner Losh seteuid(euid); 9314a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 9324a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_QUEUE_DIS) < 0) 9334a1a0dbeSGarrett Wollman printf("\tcannot disable queuing: %s\n", 9344a1a0dbeSGarrett Wollman strerror(errno)); 935dea673e9SRodney W. Grimes else 936dea673e9SRodney W. Grimes printf("\tqueuing disabled\n"); 937dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 9384a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 9394a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_QUEUE_DIS)) < 0) 9404a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 9414a1a0dbeSGarrett Wollman strerror(errno)); 942dea673e9SRodney W. Grimes else { 943dea673e9SRodney W. Grimes (void) close(fd); 944dea673e9SRodney W. Grimes printf("\tqueuing disabled\n"); 945dea673e9SRodney W. Grimes } 946dea673e9SRodney W. Grimes } else 947dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 948360d4ad5SWarner Losh seteuid(uid); 949dea673e9SRodney W. Grimes } 950dea673e9SRodney W. Grimes 951dea673e9SRodney W. Grimes /* 952e8e715faSGarance A Drosehn * Disable queuing. 953e8e715faSGarance A Drosehn */ 954e8e715faSGarance A Drosehn void 955e8e715faSGarance A Drosehn disable_q(struct printer *pp) 956e8e715faSGarance A Drosehn { 957e8e715faSGarance A Drosehn int setres; 958e8e715faSGarance A Drosehn char lf[MAXPATHLEN]; 959e8e715faSGarance A Drosehn 960e8e715faSGarance A Drosehn lock_file_name(pp, lf, sizeof lf); 961e8e715faSGarance A Drosehn printf("%s:\n", pp->printer); 962e8e715faSGarance A Drosehn 963e8e715faSGarance A Drosehn setres = set_qstate(SQS_DISABLEQ, lf); 964e8e715faSGarance A Drosehn } 965e8e715faSGarance A Drosehn 966e8e715faSGarance A Drosehn /* 967dea673e9SRodney W. Grimes * Disable queuing and printing and put a message into the status file 968dea673e9SRodney W. Grimes * (reason for being down). 969dea673e9SRodney W. Grimes */ 970dea673e9SRodney W. Grimes void 971ba7a1ad7SGarance A Drosehn down(int argc, char *argv[]) 972dea673e9SRodney W. Grimes { 973ba7a1ad7SGarance A Drosehn int cmdstatus, more; 9744a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 975dea673e9SRodney W. Grimes 976dea673e9SRodney W. Grimes if (argc == 1) { 977d3974088SDag-Erling Smørgrav printf("usage: down {all | printer} [message ...]\n"); 978dea673e9SRodney W. Grimes return; 979dea673e9SRodney W. Grimes } 980dea673e9SRodney W. Grimes if (!strcmp(argv[1], "all")) { 981ba7a1ad7SGarance A Drosehn more = firstprinter(pp, &cmdstatus); 982ba7a1ad7SGarance A Drosehn if (cmdstatus) 9834a1a0dbeSGarrett Wollman goto looperr; 9844a1a0dbeSGarrett Wollman while (more) { 9854a1a0dbeSGarrett Wollman putmsg(pp, argc - 2, argv + 2); 9864a1a0dbeSGarrett Wollman do { 987ba7a1ad7SGarance A Drosehn more = nextprinter(pp, &cmdstatus); 9884a1a0dbeSGarrett Wollman looperr: 989ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 9904a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 9914a1a0dbeSGarrett Wollman printf("warning: %s: unresolved " 9924a1a0dbeSGarrett Wollman "tc= reference(s) ", 9934a1a0dbeSGarrett Wollman pp->printer); 9944a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 9954a1a0dbeSGarrett Wollman break; 9964a1a0dbeSGarrett Wollman default: 9976d39e1b7SGarance A Drosehn fatal(pp, "%s", pcaperr(cmdstatus)); 9984a1a0dbeSGarrett Wollman } 999ba7a1ad7SGarance A Drosehn } while (more && cmdstatus); 1000dea673e9SRodney W. Grimes } 1001dea673e9SRodney W. Grimes return; 1002dea673e9SRodney W. Grimes } 10034a1a0dbeSGarrett Wollman init_printer(pp); 1004ba7a1ad7SGarance A Drosehn cmdstatus = getprintcap(argv[1], pp); 1005ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 10064a1a0dbeSGarrett Wollman default: 10076d39e1b7SGarance A Drosehn fatal(pp, "%s", pcaperr(cmdstatus)); 10084a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 10094a1a0dbeSGarrett Wollman printf("unknown printer %s\n", argv[1]); 1010dea673e9SRodney W. Grimes return; 10114a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 10124a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)", argv[1]); 10134a1a0dbeSGarrett Wollman break; 10144a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 10154a1a0dbeSGarrett Wollman break; 10164a1a0dbeSGarrett Wollman } 10174a1a0dbeSGarrett Wollman putmsg(pp, argc - 2, argv + 2); 1018dea673e9SRodney W. Grimes } 1019dea673e9SRodney W. Grimes 1020dea673e9SRodney W. Grimes static void 1021ba7a1ad7SGarance A Drosehn putmsg(struct printer *pp, int argc, char **argv) 1022dea673e9SRodney W. Grimes { 1023dea673e9SRodney W. Grimes register int fd; 1024dea673e9SRodney W. Grimes register char *cp1, *cp2; 1025dea673e9SRodney W. Grimes char buf[1024]; 10264a1a0dbeSGarrett Wollman char file[MAXPATHLEN]; 1027dea673e9SRodney W. Grimes struct stat stbuf; 1028dea673e9SRodney W. Grimes 10294a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 1030dea673e9SRodney W. Grimes /* 10314a1a0dbeSGarrett Wollman * Turn on the group execute bit of the lock file to disable queuing; 1032dea673e9SRodney W. Grimes * turn on the owner execute bit of the lock file to disable printing. 1033dea673e9SRodney W. Grimes */ 10344a1a0dbeSGarrett Wollman lock_file_name(pp, file, sizeof file); 1035360d4ad5SWarner Losh seteuid(euid); 10364a1a0dbeSGarrett Wollman if (stat(file, &stbuf) >= 0) { 10374a1a0dbeSGarrett Wollman if (chmod(file, stbuf.st_mode|LFM_PRINT_DIS|LFM_QUEUE_DIS) < 0) 10384a1a0dbeSGarrett Wollman printf("\tcannot disable queuing: %s\n", 10394a1a0dbeSGarrett Wollman strerror(errno)); 1040dea673e9SRodney W. Grimes else 1041dea673e9SRodney W. Grimes printf("\tprinter and queuing disabled\n"); 1042dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 10434a1a0dbeSGarrett Wollman if ((fd = open(file, O_WRONLY|O_CREAT, 10444a1a0dbeSGarrett Wollman LOCK_FILE_MODE|LFM_PRINT_DIS|LFM_QUEUE_DIS)) < 0) 10454a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 10464a1a0dbeSGarrett Wollman strerror(errno)); 1047dea673e9SRodney W. Grimes else { 1048dea673e9SRodney W. Grimes (void) close(fd); 1049dea673e9SRodney W. Grimes printf("\tprinter and queuing disabled\n"); 1050dea673e9SRodney W. Grimes } 1051360d4ad5SWarner Losh seteuid(uid); 1052dea673e9SRodney W. Grimes return; 1053dea673e9SRodney W. Grimes } else 1054dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 1055dea673e9SRodney W. Grimes /* 1056dea673e9SRodney W. Grimes * Write the message into the status file. 1057dea673e9SRodney W. Grimes */ 10584a1a0dbeSGarrett Wollman status_file_name(pp, file, sizeof file); 10594a1a0dbeSGarrett Wollman fd = open(file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 10604a1a0dbeSGarrett Wollman if (fd < 0) { 10614a1a0dbeSGarrett Wollman printf("\tcannot create status file: %s\n", strerror(errno)); 1062360d4ad5SWarner Losh seteuid(uid); 1063dea673e9SRodney W. Grimes return; 1064dea673e9SRodney W. Grimes } 1065360d4ad5SWarner Losh seteuid(uid); 1066dea673e9SRodney W. Grimes (void) ftruncate(fd, 0); 1067dea673e9SRodney W. Grimes if (argc <= 0) { 1068dea673e9SRodney W. Grimes (void) write(fd, "\n", 1); 1069dea673e9SRodney W. Grimes (void) close(fd); 1070dea673e9SRodney W. Grimes return; 1071dea673e9SRodney W. Grimes } 1072dea673e9SRodney W. Grimes cp1 = buf; 1073dea673e9SRodney W. Grimes while (--argc >= 0) { 1074dea673e9SRodney W. Grimes cp2 = *argv++; 107579c96a6cSGarance A Drosehn while ((size_t)(cp1 - buf) < sizeof(buf) && (*cp1++ = *cp2++)) 1076dea673e9SRodney W. Grimes ; 1077dea673e9SRodney W. Grimes cp1[-1] = ' '; 1078dea673e9SRodney W. Grimes } 1079dea673e9SRodney W. Grimes cp1[-1] = '\n'; 1080dea673e9SRodney W. Grimes *cp1 = '\0'; 1081dea673e9SRodney W. Grimes (void) write(fd, buf, strlen(buf)); 1082dea673e9SRodney W. Grimes (void) close(fd); 1083dea673e9SRodney W. Grimes } 1084dea673e9SRodney W. Grimes 1085dea673e9SRodney W. Grimes /* 1086dea673e9SRodney W. Grimes * Exit lpc 1087dea673e9SRodney W. Grimes */ 1088dea673e9SRodney W. Grimes void 1089ba7a1ad7SGarance A Drosehn quit(int argc __unused, char *argv[] __unused) 1090dea673e9SRodney W. Grimes { 1091dea673e9SRodney W. Grimes exit(0); 1092dea673e9SRodney W. Grimes } 1093dea673e9SRodney W. Grimes 1094dea673e9SRodney W. Grimes /* 1095dea673e9SRodney W. Grimes * Kill and restart the daemon. 1096dea673e9SRodney W. Grimes */ 1097dea673e9SRodney W. Grimes void 1098ba7a1ad7SGarance A Drosehn restart(struct printer *pp) 1099dea673e9SRodney W. Grimes { 11004a1a0dbeSGarrett Wollman abortpr(pp, 0); 11014a1a0dbeSGarrett Wollman startpr(pp, 0); 1102dea673e9SRodney W. Grimes } 1103dea673e9SRodney W. Grimes 1104dea673e9SRodney W. Grimes /* 1105e8e715faSGarance A Drosehn * Kill and restart the daemon. 1106e8e715faSGarance A Drosehn */ 1107e8e715faSGarance A Drosehn void 1108e8e715faSGarance A Drosehn restart_q(struct printer *pp) 1109e8e715faSGarance A Drosehn { 1110e8e715faSGarance A Drosehn int killres, setres, startok; 1111e8e715faSGarance A Drosehn char lf[MAXPATHLEN]; 1112e8e715faSGarance A Drosehn 1113e8e715faSGarance A Drosehn lock_file_name(pp, lf, sizeof lf); 1114e8e715faSGarance A Drosehn printf("%s:\n", pp->printer); 1115e8e715faSGarance A Drosehn 1116e8e715faSGarance A Drosehn killres = kill_qtask(lf); 1117e8e715faSGarance A Drosehn 1118e8e715faSGarance A Drosehn /* 1119e8e715faSGarance A Drosehn * XXX - if the kill worked, we should probably sleep for 1120e8e715faSGarance A Drosehn * a second or so before trying to restart the queue. 1121e8e715faSGarance A Drosehn */ 1122e8e715faSGarance A Drosehn 1123e8e715faSGarance A Drosehn /* make sure the queue is set to print jobs */ 1124e8e715faSGarance A Drosehn setres = set_qstate(SQS_STARTP, lf); 1125e8e715faSGarance A Drosehn 1126e8e715faSGarance A Drosehn seteuid(euid); 1127e8e715faSGarance A Drosehn startok = startdaemon(pp); 1128e8e715faSGarance A Drosehn seteuid(uid); 1129e8e715faSGarance A Drosehn if (!startok) 1130e8e715faSGarance A Drosehn printf("\tcouldn't restart daemon\n"); 1131e8e715faSGarance A Drosehn else 1132e8e715faSGarance A Drosehn printf("\tdaemon restarted\n"); 1133e8e715faSGarance A Drosehn } 1134e8e715faSGarance A Drosehn 1135e8e715faSGarance A Drosehn /* 1136dea673e9SRodney W. Grimes * Enable printing on the specified printer and startup the daemon. 1137dea673e9SRodney W. Grimes */ 1138dea673e9SRodney W. Grimes void 1139ba7a1ad7SGarance A Drosehn startcmd(struct printer *pp) 1140dea673e9SRodney W. Grimes { 11414a1a0dbeSGarrett Wollman startpr(pp, 1); 1142dea673e9SRodney W. Grimes } 1143dea673e9SRodney W. Grimes 1144dea673e9SRodney W. Grimes static void 1145ba7a1ad7SGarance A Drosehn startpr(struct printer *pp, int chgenable) 1146dea673e9SRodney W. Grimes { 1147dea673e9SRodney W. Grimes struct stat stbuf; 11484a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 1149dea673e9SRodney W. Grimes 11504a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 11514a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 1152dea673e9SRodney W. Grimes 1153dea673e9SRodney W. Grimes /* 1154ba7a1ad7SGarance A Drosehn * For chgenable==1 ('start'), turn off the LFM_PRINT_DIS bit of the 1155ba7a1ad7SGarance A Drosehn * lock file to re-enable printing. For chgenable==2 ('up'), also 11561bd87e1bSMatthew Dillon * turn off the LFM_QUEUE_DIS bit to re-enable queueing. 1157dea673e9SRodney W. Grimes */ 1158360d4ad5SWarner Losh seteuid(euid); 1159ba7a1ad7SGarance A Drosehn if (chgenable && stat(lf, &stbuf) >= 0) { 1160ba7a1ad7SGarance A Drosehn mode_t bits = (chgenable == 2 ? 0 : LFM_QUEUE_DIS); 11614a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode & (LOCK_FILE_MODE | bits)) < 0) 1162dea673e9SRodney W. Grimes printf("\tcannot enable printing\n"); 1163dea673e9SRodney W. Grimes else 1164dea673e9SRodney W. Grimes printf("\tprinting enabled\n"); 1165dea673e9SRodney W. Grimes } 11664a1a0dbeSGarrett Wollman if (!startdaemon(pp)) 1167dea673e9SRodney W. Grimes printf("\tcouldn't start daemon\n"); 1168dea673e9SRodney W. Grimes else 1169dea673e9SRodney W. Grimes printf("\tdaemon started\n"); 1170360d4ad5SWarner Losh seteuid(uid); 1171dea673e9SRodney W. Grimes } 1172dea673e9SRodney W. Grimes 1173dea673e9SRodney W. Grimes /* 1174e8e715faSGarance A Drosehn * Enable printing on the specified printer and startup the daemon. 1175e8e715faSGarance A Drosehn */ 1176e8e715faSGarance A Drosehn void 1177e8e715faSGarance A Drosehn start_q(struct printer *pp) 1178e8e715faSGarance A Drosehn { 1179e8e715faSGarance A Drosehn int setres, startok; 1180e8e715faSGarance A Drosehn char lf[MAXPATHLEN]; 1181e8e715faSGarance A Drosehn 1182e8e715faSGarance A Drosehn lock_file_name(pp, lf, sizeof lf); 1183e8e715faSGarance A Drosehn printf("%s:\n", pp->printer); 1184e8e715faSGarance A Drosehn 1185e8e715faSGarance A Drosehn setres = set_qstate(SQS_STARTP, lf); 1186e8e715faSGarance A Drosehn 1187e8e715faSGarance A Drosehn seteuid(euid); 1188e8e715faSGarance A Drosehn startok = startdaemon(pp); 1189e8e715faSGarance A Drosehn seteuid(uid); 1190e8e715faSGarance A Drosehn if (!startok) 1191e8e715faSGarance A Drosehn printf("\tcouldn't start daemon\n"); 1192e8e715faSGarance A Drosehn else 1193e8e715faSGarance A Drosehn printf("\tdaemon started\n"); 1194e8e715faSGarance A Drosehn seteuid(uid); 1195e8e715faSGarance A Drosehn } 1196e8e715faSGarance A Drosehn 1197e8e715faSGarance A Drosehn /* 1198dea673e9SRodney W. Grimes * Print the status of the printer queue. 1199dea673e9SRodney W. Grimes */ 12004a1a0dbeSGarrett Wollman void 1201ba7a1ad7SGarance A Drosehn status(struct printer *pp) 1202dea673e9SRodney W. Grimes { 1203dea673e9SRodney W. Grimes struct stat stbuf; 1204dea673e9SRodney W. Grimes register int fd, i; 1205dea673e9SRodney W. Grimes register struct dirent *dp; 1206dea673e9SRodney W. Grimes DIR *dirp; 12074a1a0dbeSGarrett Wollman char file[MAXPATHLEN]; 1208dea673e9SRodney W. Grimes 12094a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 12104a1a0dbeSGarrett Wollman lock_file_name(pp, file, sizeof file); 12114a1a0dbeSGarrett Wollman if (stat(file, &stbuf) >= 0) { 1212dea673e9SRodney W. Grimes printf("\tqueuing is %s\n", 12134a1a0dbeSGarrett Wollman ((stbuf.st_mode & LFM_QUEUE_DIS) ? "disabled" 12144a1a0dbeSGarrett Wollman : "enabled")); 1215dea673e9SRodney W. Grimes printf("\tprinting is %s\n", 12164a1a0dbeSGarrett Wollman ((stbuf.st_mode & LFM_PRINT_DIS) ? "disabled" 12174a1a0dbeSGarrett Wollman : "enabled")); 1218dea673e9SRodney W. Grimes } else { 1219dea673e9SRodney W. Grimes printf("\tqueuing is enabled\n"); 1220dea673e9SRodney W. Grimes printf("\tprinting is enabled\n"); 1221dea673e9SRodney W. Grimes } 12224a1a0dbeSGarrett Wollman if ((dirp = opendir(pp->spool_dir)) == NULL) { 1223dea673e9SRodney W. Grimes printf("\tcannot examine spool directory\n"); 1224dea673e9SRodney W. Grimes return; 1225dea673e9SRodney W. Grimes } 1226dea673e9SRodney W. Grimes i = 0; 1227dea673e9SRodney W. Grimes while ((dp = readdir(dirp)) != NULL) { 1228dea673e9SRodney W. Grimes if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 1229dea673e9SRodney W. Grimes i++; 1230dea673e9SRodney W. Grimes } 1231dea673e9SRodney W. Grimes closedir(dirp); 1232dea673e9SRodney W. Grimes if (i == 0) 12334a1a0dbeSGarrett Wollman printf("\tno entries in spool area\n"); 1234dea673e9SRodney W. Grimes else if (i == 1) 1235dea673e9SRodney W. Grimes printf("\t1 entry in spool area\n"); 1236dea673e9SRodney W. Grimes else 1237dea673e9SRodney W. Grimes printf("\t%d entries in spool area\n", i); 12384a1a0dbeSGarrett Wollman fd = open(file, O_RDONLY); 1239dea673e9SRodney W. Grimes if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 1240dea673e9SRodney W. Grimes (void) close(fd); /* unlocks as well */ 1241bc407914SWarner Losh printf("\tprinter idle\n"); 1242dea673e9SRodney W. Grimes return; 1243dea673e9SRodney W. Grimes } 1244dea673e9SRodney W. Grimes (void) close(fd); 124536abea5dSBrian Somers /* print out the contents of the status file, if it exists */ 12464a1a0dbeSGarrett Wollman status_file_name(pp, file, sizeof file); 12474a1a0dbeSGarrett Wollman fd = open(file, O_RDONLY|O_SHLOCK); 1248dea673e9SRodney W. Grimes if (fd >= 0) { 124936abea5dSBrian Somers (void) fstat(fd, &stbuf); 125036abea5dSBrian Somers if (stbuf.st_size > 0) { 125136abea5dSBrian Somers putchar('\t'); 1252dea673e9SRodney W. Grimes while ((i = read(fd, line, sizeof(line))) > 0) 1253dea673e9SRodney W. Grimes (void) fwrite(line, 1, i, stdout); 125436abea5dSBrian Somers } 1255dea673e9SRodney W. Grimes (void) close(fd); /* unlocks as well */ 1256dea673e9SRodney W. Grimes } 1257dea673e9SRodney W. Grimes } 1258dea673e9SRodney W. Grimes 1259dea673e9SRodney W. Grimes /* 1260dea673e9SRodney W. Grimes * Stop the specified daemon after completing the current job and disable 1261dea673e9SRodney W. Grimes * printing. 1262dea673e9SRodney W. Grimes */ 1263dea673e9SRodney W. Grimes void 1264ba7a1ad7SGarance A Drosehn stop(struct printer *pp) 1265dea673e9SRodney W. Grimes { 1266dea673e9SRodney W. Grimes register int fd; 1267dea673e9SRodney W. Grimes struct stat stbuf; 12684a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 1269dea673e9SRodney W. Grimes 12704a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 12714a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 1272dea673e9SRodney W. Grimes 1273dea673e9SRodney W. Grimes /* 1274dea673e9SRodney W. Grimes * Turn on the owner execute bit of the lock file to disable printing. 1275dea673e9SRodney W. Grimes */ 1276360d4ad5SWarner Losh seteuid(euid); 12774a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 12784a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 12794a1a0dbeSGarrett Wollman printf("\tcannot disable printing: %s\n", 12804a1a0dbeSGarrett Wollman strerror(errno)); 1281dea673e9SRodney W. Grimes else { 12824a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 1283dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 1284dea673e9SRodney W. Grimes } 1285dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 12864a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 12874a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 12884a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 12894a1a0dbeSGarrett Wollman strerror(errno)); 1290dea673e9SRodney W. Grimes else { 1291dea673e9SRodney W. Grimes (void) close(fd); 12924a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 1293dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 1294dea673e9SRodney W. Grimes } 1295dea673e9SRodney W. Grimes } else 1296dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 1297360d4ad5SWarner Losh seteuid(uid); 1298dea673e9SRodney W. Grimes } 1299dea673e9SRodney W. Grimes 1300e8e715faSGarance A Drosehn /* 1301e8e715faSGarance A Drosehn * Stop the specified daemon after completing the current job and disable 1302e8e715faSGarance A Drosehn * printing. 1303e8e715faSGarance A Drosehn */ 1304e8e715faSGarance A Drosehn void 1305e8e715faSGarance A Drosehn stop_q(struct printer *pp) 1306e8e715faSGarance A Drosehn { 1307e8e715faSGarance A Drosehn int setres; 1308e8e715faSGarance A Drosehn char lf[MAXPATHLEN]; 1309e8e715faSGarance A Drosehn 1310e8e715faSGarance A Drosehn lock_file_name(pp, lf, sizeof lf); 1311e8e715faSGarance A Drosehn printf("%s:\n", pp->printer); 1312e8e715faSGarance A Drosehn 1313e8e715faSGarance A Drosehn setres = set_qstate(SQS_STOPP, lf); 1314e8e715faSGarance A Drosehn 1315e8e715faSGarance A Drosehn if (setres >= 0) { 1316e8e715faSGarance A Drosehn seteuid(euid); 1317e8e715faSGarance A Drosehn upstat(pp, "printing disabled\n"); 1318e8e715faSGarance A Drosehn seteuid(uid); 1319e8e715faSGarance A Drosehn } 1320e8e715faSGarance A Drosehn } 1321e8e715faSGarance A Drosehn 132230b4b758SGarance A Drosehn struct jobqueue **queue; 1323dea673e9SRodney W. Grimes int nitems; 1324dea673e9SRodney W. Grimes time_t mtime; 1325dea673e9SRodney W. Grimes 1326dea673e9SRodney W. Grimes /* 1327dea673e9SRodney W. Grimes * Put the specified jobs at the top of printer queue. 1328dea673e9SRodney W. Grimes */ 1329dea673e9SRodney W. Grimes void 1330ba7a1ad7SGarance A Drosehn topq(int argc, char *argv[]) 1331dea673e9SRodney W. Grimes { 1332dea673e9SRodney W. Grimes register int i; 1333dea673e9SRodney W. Grimes struct stat stbuf; 1334ba7a1ad7SGarance A Drosehn int cmdstatus, changed; 13354a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 1336dea673e9SRodney W. Grimes 1337dea673e9SRodney W. Grimes if (argc < 3) { 1338d3974088SDag-Erling Smørgrav printf("usage: topq printer [jobnum ...] [user ...]\n"); 1339dea673e9SRodney W. Grimes return; 1340dea673e9SRodney W. Grimes } 1341dea673e9SRodney W. Grimes 1342dea673e9SRodney W. Grimes --argc; 13434a1a0dbeSGarrett Wollman ++argv; 13444a1a0dbeSGarrett Wollman init_printer(pp); 1345ba7a1ad7SGarance A Drosehn cmdstatus = getprintcap(*argv, pp); 1346ba7a1ad7SGarance A Drosehn switch(cmdstatus) { 13474a1a0dbeSGarrett Wollman default: 13486d39e1b7SGarance A Drosehn fatal(pp, "%s", pcaperr(cmdstatus)); 13494a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 13504a1a0dbeSGarrett Wollman printf("unknown printer %s\n", *argv); 1351dea673e9SRodney W. Grimes return; 13524a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 13534a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)", *argv); 13544a1a0dbeSGarrett Wollman break; 13554a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 13564a1a0dbeSGarrett Wollman break; 13574a1a0dbeSGarrett Wollman } 13584a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 1359dea673e9SRodney W. Grimes 1360360d4ad5SWarner Losh seteuid(euid); 13614a1a0dbeSGarrett Wollman if (chdir(pp->spool_dir) < 0) { 13624a1a0dbeSGarrett Wollman printf("\tcannot chdir to %s\n", pp->spool_dir); 1363360d4ad5SWarner Losh goto out; 1364dea673e9SRodney W. Grimes } 1365360d4ad5SWarner Losh seteuid(uid); 13664a1a0dbeSGarrett Wollman nitems = getq(pp, &queue); 1367dea673e9SRodney W. Grimes if (nitems == 0) 1368dea673e9SRodney W. Grimes return; 1369dea673e9SRodney W. Grimes changed = 0; 137030b4b758SGarance A Drosehn mtime = queue[0]->job_time; 1371dea673e9SRodney W. Grimes for (i = argc; --i; ) { 1372dea673e9SRodney W. Grimes if (doarg(argv[i]) == 0) { 1373dea673e9SRodney W. Grimes printf("\tjob %s is not in the queue\n", argv[i]); 1374dea673e9SRodney W. Grimes continue; 1375dea673e9SRodney W. Grimes } else 1376dea673e9SRodney W. Grimes changed++; 1377dea673e9SRodney W. Grimes } 1378dea673e9SRodney W. Grimes for (i = 0; i < nitems; i++) 1379dea673e9SRodney W. Grimes free(queue[i]); 1380dea673e9SRodney W. Grimes free(queue); 1381dea673e9SRodney W. Grimes if (!changed) { 1382dea673e9SRodney W. Grimes printf("\tqueue order unchanged\n"); 1383dea673e9SRodney W. Grimes return; 1384dea673e9SRodney W. Grimes } 1385dea673e9SRodney W. Grimes /* 1386dea673e9SRodney W. Grimes * Turn on the public execute bit of the lock file to 1387dea673e9SRodney W. Grimes * get lpd to rebuild the queue after the current job. 1388dea673e9SRodney W. Grimes */ 1389360d4ad5SWarner Losh seteuid(euid); 13904a1a0dbeSGarrett Wollman if (changed && stat(pp->lock_file, &stbuf) >= 0) 13914a1a0dbeSGarrett Wollman (void) chmod(pp->lock_file, stbuf.st_mode | LFM_RESET_QUE); 1392360d4ad5SWarner Losh 1393360d4ad5SWarner Losh out: 1394360d4ad5SWarner Losh seteuid(uid); 1395dea673e9SRodney W. Grimes } 1396dea673e9SRodney W. Grimes 1397dea673e9SRodney W. Grimes /* 1398dea673e9SRodney W. Grimes * Reposition the job by changing the modification time of 1399dea673e9SRodney W. Grimes * the control file. 1400dea673e9SRodney W. Grimes */ 1401dea673e9SRodney W. Grimes static int 1402ba7a1ad7SGarance A Drosehn touch(struct jobqueue *jq) 1403dea673e9SRodney W. Grimes { 1404dea673e9SRodney W. Grimes struct timeval tvp[2]; 1405360d4ad5SWarner Losh int ret; 1406dea673e9SRodney W. Grimes 1407dea673e9SRodney W. Grimes tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 1408dea673e9SRodney W. Grimes tvp[0].tv_usec = tvp[1].tv_usec = 0; 1409360d4ad5SWarner Losh seteuid(euid); 1410ba7a1ad7SGarance A Drosehn ret = utimes(jq->job_cfname, tvp); 1411360d4ad5SWarner Losh seteuid(uid); 1412360d4ad5SWarner Losh return (ret); 1413dea673e9SRodney W. Grimes } 1414dea673e9SRodney W. Grimes 1415dea673e9SRodney W. Grimes /* 1416dea673e9SRodney W. Grimes * Checks if specified job name is in the printer's queue. 1417dea673e9SRodney W. Grimes * Returns: negative (-1) if argument name is not in the queue. 1418dea673e9SRodney W. Grimes */ 1419dea673e9SRodney W. Grimes static int 1420ba7a1ad7SGarance A Drosehn doarg(char *job) 1421dea673e9SRodney W. Grimes { 142230b4b758SGarance A Drosehn register struct jobqueue **qq; 1423dea673e9SRodney W. Grimes register int jobnum, n; 1424dea673e9SRodney W. Grimes register char *cp, *machine; 1425dea673e9SRodney W. Grimes int cnt = 0; 1426dea673e9SRodney W. Grimes FILE *fp; 1427dea673e9SRodney W. Grimes 1428dea673e9SRodney W. Grimes /* 1429dea673e9SRodney W. Grimes * Look for a job item consisting of system name, colon, number 1430dea673e9SRodney W. Grimes * (example: ucbarpa:114) 1431dea673e9SRodney W. Grimes */ 1432f8eb25daSWarner Losh if ((cp = strchr(job, ':')) != NULL) { 1433dea673e9SRodney W. Grimes machine = job; 1434dea673e9SRodney W. Grimes *cp++ = '\0'; 1435dea673e9SRodney W. Grimes job = cp; 1436dea673e9SRodney W. Grimes } else 1437dea673e9SRodney W. Grimes machine = NULL; 1438dea673e9SRodney W. Grimes 1439dea673e9SRodney W. Grimes /* 1440dea673e9SRodney W. Grimes * Check for job specified by number (example: 112 or 235ucbarpa). 1441dea673e9SRodney W. Grimes */ 1442dea673e9SRodney W. Grimes if (isdigit(*job)) { 1443dea673e9SRodney W. Grimes jobnum = 0; 1444dea673e9SRodney W. Grimes do 1445dea673e9SRodney W. Grimes jobnum = jobnum * 10 + (*job++ - '0'); 1446dea673e9SRodney W. Grimes while (isdigit(*job)); 1447dea673e9SRodney W. Grimes for (qq = queue + nitems; --qq >= queue; ) { 1448dea673e9SRodney W. Grimes n = 0; 144930b4b758SGarance A Drosehn for (cp = (*qq)->job_cfname+3; isdigit(*cp); ) 1450dea673e9SRodney W. Grimes n = n * 10 + (*cp++ - '0'); 1451dea673e9SRodney W. Grimes if (jobnum != n) 1452dea673e9SRodney W. Grimes continue; 1453dea673e9SRodney W. Grimes if (*job && strcmp(job, cp) != 0) 1454dea673e9SRodney W. Grimes continue; 1455dea673e9SRodney W. Grimes if (machine != NULL && strcmp(machine, cp) != 0) 1456dea673e9SRodney W. Grimes continue; 1457dea673e9SRodney W. Grimes if (touch(*qq) == 0) { 145830b4b758SGarance A Drosehn printf("\tmoved %s\n", (*qq)->job_cfname); 1459dea673e9SRodney W. Grimes cnt++; 1460dea673e9SRodney W. Grimes } 1461dea673e9SRodney W. Grimes } 1462dea673e9SRodney W. Grimes return(cnt); 1463dea673e9SRodney W. Grimes } 1464dea673e9SRodney W. Grimes /* 1465dea673e9SRodney W. Grimes * Process item consisting of owner's name (example: henry). 1466dea673e9SRodney W. Grimes */ 1467dea673e9SRodney W. Grimes for (qq = queue + nitems; --qq >= queue; ) { 1468360d4ad5SWarner Losh seteuid(euid); 146930b4b758SGarance A Drosehn fp = fopen((*qq)->job_cfname, "r"); 1470360d4ad5SWarner Losh seteuid(uid); 1471360d4ad5SWarner Losh if (fp == NULL) 1472dea673e9SRodney W. Grimes continue; 1473dea673e9SRodney W. Grimes while (getline(fp) > 0) 1474dea673e9SRodney W. Grimes if (line[0] == 'P') 1475dea673e9SRodney W. Grimes break; 1476dea673e9SRodney W. Grimes (void) fclose(fp); 1477dea673e9SRodney W. Grimes if (line[0] != 'P' || strcmp(job, line+1) != 0) 1478dea673e9SRodney W. Grimes continue; 1479dea673e9SRodney W. Grimes if (touch(*qq) == 0) { 148030b4b758SGarance A Drosehn printf("\tmoved %s\n", (*qq)->job_cfname); 1481dea673e9SRodney W. Grimes cnt++; 1482dea673e9SRodney W. Grimes } 1483dea673e9SRodney W. Grimes } 1484dea673e9SRodney W. Grimes return(cnt); 1485dea673e9SRodney W. Grimes } 1486dea673e9SRodney W. Grimes 1487dea673e9SRodney W. Grimes /* 1488dea673e9SRodney W. Grimes * Enable everything and start printer (undo `down'). 1489dea673e9SRodney W. Grimes */ 1490dea673e9SRodney W. Grimes void 1491ba7a1ad7SGarance A Drosehn up(struct printer *pp) 1492dea673e9SRodney W. Grimes { 14934a1a0dbeSGarrett Wollman startpr(pp, 2); 1494dea673e9SRodney W. Grimes } 1495e8e715faSGarance A Drosehn 1496e8e715faSGarance A Drosehn /* 1497e8e715faSGarance A Drosehn * Enable both queuing & printing, and start printer (undo `down'). 1498e8e715faSGarance A Drosehn */ 1499e8e715faSGarance A Drosehn void 1500e8e715faSGarance A Drosehn up_q(struct printer *pp) 1501e8e715faSGarance A Drosehn { 1502e8e715faSGarance A Drosehn int setres, startok; 1503e8e715faSGarance A Drosehn char lf[MAXPATHLEN]; 1504e8e715faSGarance A Drosehn 1505e8e715faSGarance A Drosehn lock_file_name(pp, lf, sizeof lf); 1506e8e715faSGarance A Drosehn printf("%s:\n", pp->printer); 1507e8e715faSGarance A Drosehn 1508e8e715faSGarance A Drosehn setres = set_qstate(SQS_ENABLEQ+SQS_STARTP, lf); 1509e8e715faSGarance A Drosehn 1510e8e715faSGarance A Drosehn seteuid(euid); 1511e8e715faSGarance A Drosehn startok = startdaemon(pp); 1512e8e715faSGarance A Drosehn seteuid(uid); 1513e8e715faSGarance A Drosehn if (!startok) 1514e8e715faSGarance A Drosehn printf("\tcouldn't start daemon\n"); 1515e8e715faSGarance A Drosehn else 1516e8e715faSGarance A Drosehn printf("\tdaemon started\n"); 1517e8e715faSGarance A Drosehn } 1518