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 73ba7a1ad7SGarance A Drosehn static void abortpr(struct printer *_pp, int _dis); 74ba7a1ad7SGarance A Drosehn static int doarg(char *_job); 75ba7a1ad7SGarance A Drosehn static int doselect(struct dirent *_d); 76ba7a1ad7SGarance A Drosehn static void putmsg(struct printer *_pp, int _argc, char **_argv); 77ba7a1ad7SGarance A Drosehn static int sortq(const void *_a, const void *_b); 78ba7a1ad7SGarance A Drosehn static void startpr(struct printer *_pp, int _chgenable); 79ba7a1ad7SGarance A Drosehn static int touch(struct jobqueue *_jq); 80ba7a1ad7SGarance A Drosehn static void unlinkf(char *_name); 81ba7a1ad7SGarance A Drosehn static void upstat(struct printer *_pp, const char *_msg); 824a1a0dbeSGarrett Wollman 834a1a0dbeSGarrett Wollman /* 844a1a0dbeSGarrett Wollman * generic framework for commands which operate on all or a specified 854a1a0dbeSGarrett Wollman * set of printers 864a1a0dbeSGarrett Wollman */ 874a1a0dbeSGarrett Wollman void 88ba7a1ad7SGarance A Drosehn generic(void (*specificrtn)(struct printer *_pp), int argc, char *argv[]) 894a1a0dbeSGarrett Wollman { 90ba7a1ad7SGarance A Drosehn int cmdstatus, more; 914a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 924a1a0dbeSGarrett Wollman 934a1a0dbeSGarrett Wollman if (argc == 1) { 944a1a0dbeSGarrett Wollman printf("Usage: %s {all | printer ...}\n", argv[0]); 954a1a0dbeSGarrett Wollman return; 964a1a0dbeSGarrett Wollman } 974a1a0dbeSGarrett Wollman if (argc == 2 && strcmp(argv[1], "all") == 0) { 98ba7a1ad7SGarance A Drosehn more = firstprinter(pp, &cmdstatus); 99ba7a1ad7SGarance A Drosehn if (cmdstatus) 1004a1a0dbeSGarrett Wollman goto looperr; 1014a1a0dbeSGarrett Wollman while (more) { 102ba7a1ad7SGarance A Drosehn (*specificrtn)(pp); 1034a1a0dbeSGarrett Wollman do { 104ba7a1ad7SGarance A Drosehn more = nextprinter(pp, &cmdstatus); 1054a1a0dbeSGarrett Wollman looperr: 106ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 1074a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 1084a1a0dbeSGarrett Wollman printf("warning: %s: unresolved " 1094a1a0dbeSGarrett Wollman "tc= reference(s) ", 1104a1a0dbeSGarrett Wollman pp->printer); 1114a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 1124a1a0dbeSGarrett Wollman break; 1134a1a0dbeSGarrett Wollman default: 114ba7a1ad7SGarance A Drosehn fatal(pp, pcaperr(cmdstatus)); 1154a1a0dbeSGarrett Wollman } 116ba7a1ad7SGarance A Drosehn } while (more && cmdstatus); 1174a1a0dbeSGarrett Wollman } 1184a1a0dbeSGarrett Wollman return; 1194a1a0dbeSGarrett Wollman } 1204a1a0dbeSGarrett Wollman while (--argc) { 1214a1a0dbeSGarrett Wollman ++argv; 1224a1a0dbeSGarrett Wollman init_printer(pp); 123ba7a1ad7SGarance A Drosehn cmdstatus = getprintcap(*argv, pp); 124ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 1254a1a0dbeSGarrett Wollman default: 126ba7a1ad7SGarance A Drosehn fatal(pp, pcaperr(cmdstatus)); 1274a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 1284a1a0dbeSGarrett Wollman printf("unknown printer %s\n", *argv); 1294a1a0dbeSGarrett Wollman continue; 1304a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 1314a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)\n", 1324a1a0dbeSGarrett Wollman *argv); 1334a1a0dbeSGarrett Wollman break; 1344a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 1354a1a0dbeSGarrett Wollman break; 1364a1a0dbeSGarrett Wollman } 137ba7a1ad7SGarance A Drosehn (*specificrtn)(pp); 1384a1a0dbeSGarrett Wollman } 1394a1a0dbeSGarrett Wollman } 140dea673e9SRodney W. Grimes 141dea673e9SRodney W. Grimes /* 142dea673e9SRodney W. Grimes * kill an existing daemon and disable printing. 143dea673e9SRodney W. Grimes */ 144dea673e9SRodney W. Grimes void 145ba7a1ad7SGarance A Drosehn doabort(struct printer *pp) 146dea673e9SRodney W. Grimes { 1474a1a0dbeSGarrett Wollman abortpr(pp, 1); 148dea673e9SRodney W. Grimes } 149dea673e9SRodney W. Grimes 150dea673e9SRodney W. Grimes static void 151ba7a1ad7SGarance A Drosehn abortpr(struct printer *pp, int dis) 152dea673e9SRodney W. Grimes { 153dea673e9SRodney W. Grimes register FILE *fp; 154dea673e9SRodney W. Grimes struct stat stbuf; 155dea673e9SRodney W. Grimes int pid, fd; 1564a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 157dea673e9SRodney W. Grimes 1584a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 1594a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 160dea673e9SRodney W. Grimes 161dea673e9SRodney W. Grimes /* 162dea673e9SRodney W. Grimes * Turn on the owner execute bit of the lock file to disable printing. 163dea673e9SRodney W. Grimes */ 164dea673e9SRodney W. Grimes if (dis) { 165360d4ad5SWarner Losh seteuid(euid); 1664a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 1674a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 1684a1a0dbeSGarrett Wollman printf("\tcannot disable printing: %s\n", 1694a1a0dbeSGarrett Wollman strerror(errno)); 170dea673e9SRodney W. Grimes else { 1714a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 172dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 173dea673e9SRodney W. Grimes } 174dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 1754a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 1764a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 1774a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 1784a1a0dbeSGarrett Wollman strerror(errno)); 179dea673e9SRodney W. Grimes else { 180dea673e9SRodney W. Grimes (void) close(fd); 1814a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 182dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 183dea673e9SRodney W. Grimes printf("\tno daemon to abort\n"); 184dea673e9SRodney W. Grimes } 185360d4ad5SWarner Losh goto out; 186dea673e9SRodney W. Grimes } else { 187dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 188360d4ad5SWarner Losh goto out; 189dea673e9SRodney W. Grimes } 190dea673e9SRodney W. Grimes } 191dea673e9SRodney W. Grimes /* 192dea673e9SRodney W. Grimes * Kill the current daemon to stop printing now. 193dea673e9SRodney W. Grimes */ 1944a1a0dbeSGarrett Wollman if ((fp = fopen(lf, "r")) == NULL) { 195dea673e9SRodney W. Grimes printf("\tcannot open lock file\n"); 196360d4ad5SWarner Losh goto out; 197dea673e9SRodney W. Grimes } 198dea673e9SRodney W. Grimes if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 199dea673e9SRodney W. Grimes (void) fclose(fp); /* unlocks as well */ 200dea673e9SRodney W. Grimes printf("\tno daemon to abort\n"); 201360d4ad5SWarner Losh goto out; 202dea673e9SRodney W. Grimes } 203dea673e9SRodney W. Grimes (void) fclose(fp); 204360d4ad5SWarner Losh if (kill(pid = atoi(line), SIGTERM) < 0) { 205360d4ad5SWarner Losh if (errno == ESRCH) 206360d4ad5SWarner Losh printf("\tno daemon to abort\n"); 207dea673e9SRodney W. Grimes else 208360d4ad5SWarner Losh printf("\tWarning: daemon (pid %d) not killed\n", pid); 209360d4ad5SWarner Losh } else 210dea673e9SRodney W. Grimes printf("\tdaemon (pid %d) killed\n", pid); 211360d4ad5SWarner Losh out: 212360d4ad5SWarner Losh seteuid(uid); 213dea673e9SRodney W. Grimes } 214dea673e9SRodney W. Grimes 215dea673e9SRodney W. Grimes /* 216dea673e9SRodney W. Grimes * Write a message into the status file. 217dea673e9SRodney W. Grimes */ 218dea673e9SRodney W. Grimes static void 219ba7a1ad7SGarance A Drosehn upstat(struct printer *pp, const char *msg) 220dea673e9SRodney W. Grimes { 221dea673e9SRodney W. Grimes register int fd; 2225f87a7b6SWarner Losh char statfile[MAXPATHLEN]; 223dea673e9SRodney W. Grimes 2244a1a0dbeSGarrett Wollman status_file_name(pp, statfile, sizeof statfile); 225dea673e9SRodney W. Grimes umask(0); 2264a1a0dbeSGarrett Wollman fd = open(statfile, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 2274a1a0dbeSGarrett Wollman if (fd < 0) { 2284a1a0dbeSGarrett Wollman printf("\tcannot create status file: %s\n", strerror(errno)); 229dea673e9SRodney W. Grimes return; 230dea673e9SRodney W. Grimes } 231dea673e9SRodney W. Grimes (void) ftruncate(fd, 0); 232dea673e9SRodney W. Grimes if (msg == (char *)NULL) 233dea673e9SRodney W. Grimes (void) write(fd, "\n", 1); 234dea673e9SRodney W. Grimes else 235dea673e9SRodney W. Grimes (void) write(fd, msg, strlen(msg)); 236dea673e9SRodney W. Grimes (void) close(fd); 237dea673e9SRodney W. Grimes } 238dea673e9SRodney W. Grimes 239dea673e9SRodney W. Grimes static int 240ba7a1ad7SGarance A Drosehn doselect(struct dirent *d) 241dea673e9SRodney W. Grimes { 242dea673e9SRodney W. Grimes int c = d->d_name[0]; 243dea673e9SRodney W. Grimes 244dea673e9SRodney W. Grimes if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 245dea673e9SRodney W. Grimes return(1); 246dea673e9SRodney W. Grimes return(0); 247dea673e9SRodney W. Grimes } 248dea673e9SRodney W. Grimes 249dea673e9SRodney W. Grimes /* 250dea673e9SRodney W. Grimes * Comparison routine for scandir. Sort by job number and machine, then 251dea673e9SRodney W. Grimes * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 252dea673e9SRodney W. Grimes */ 253dea673e9SRodney W. Grimes static int 254ba7a1ad7SGarance A Drosehn sortq(const void *a, const void *b) 255dea673e9SRodney W. Grimes { 256ba7a1ad7SGarance A Drosehn const struct dirent **d1, **d2; 257dea673e9SRodney W. Grimes int c1, c2; 258dea673e9SRodney W. Grimes 259ba7a1ad7SGarance A Drosehn d1 = (const struct dirent **)a; 260ba7a1ad7SGarance A Drosehn d2 = (const struct dirent **)b; 261bc407914SWarner Losh if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))) 262dea673e9SRodney W. Grimes return(c1); 263dea673e9SRodney W. Grimes c1 = (*d1)->d_name[0]; 264dea673e9SRodney W. Grimes c2 = (*d2)->d_name[0]; 265dea673e9SRodney W. Grimes if (c1 == c2) 266dea673e9SRodney W. Grimes return((*d1)->d_name[2] - (*d2)->d_name[2]); 267dea673e9SRodney W. Grimes if (c1 == 'c') 268dea673e9SRodney W. Grimes return(-1); 269dea673e9SRodney W. Grimes if (c1 == 'd' || c2 == 'c') 270dea673e9SRodney W. Grimes return(1); 271dea673e9SRodney W. Grimes return(-1); 272dea673e9SRodney W. Grimes } 273dea673e9SRodney W. Grimes 274dea673e9SRodney W. Grimes /* 2754a1a0dbeSGarrett Wollman * Remove all spool files and temporaries from the spooling area. 2764a1a0dbeSGarrett Wollman * Or, perhaps: 277dea673e9SRodney W. Grimes * Remove incomplete jobs from spooling area. 278dea673e9SRodney W. Grimes */ 2794a1a0dbeSGarrett Wollman void 280ba7a1ad7SGarance A Drosehn clean(struct printer *pp) 281dea673e9SRodney W. Grimes { 282dea673e9SRodney W. Grimes register int i, n; 283dea673e9SRodney W. Grimes register char *cp, *cp1, *lp; 284dea673e9SRodney W. Grimes struct dirent **queue; 285dea673e9SRodney W. Grimes int nitems; 286dea673e9SRodney W. Grimes 2874a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 288dea673e9SRodney W. Grimes 2894a1a0dbeSGarrett Wollman lp = line; 2904a1a0dbeSGarrett Wollman cp = pp->spool_dir; 2914a1a0dbeSGarrett Wollman while (lp < &line[sizeof(line) - 1]) { 2924a1a0dbeSGarrett Wollman if ((*lp++ = *cp++) == 0) 2934a1a0dbeSGarrett Wollman break; 2944a1a0dbeSGarrett Wollman } 295dea673e9SRodney W. Grimes lp[-1] = '/'; 296dea673e9SRodney W. Grimes 297360d4ad5SWarner Losh seteuid(euid); 2984a1a0dbeSGarrett Wollman nitems = scandir(pp->spool_dir, &queue, doselect, sortq); 299360d4ad5SWarner Losh seteuid(uid); 300dea673e9SRodney W. Grimes if (nitems < 0) { 301dea673e9SRodney W. Grimes printf("\tcannot examine spool directory\n"); 302dea673e9SRodney W. Grimes return; 303dea673e9SRodney W. Grimes } 304dea673e9SRodney W. Grimes if (nitems == 0) 305dea673e9SRodney W. Grimes return; 306dea673e9SRodney W. Grimes i = 0; 307dea673e9SRodney W. Grimes do { 308dea673e9SRodney W. Grimes cp = queue[i]->d_name; 309dea673e9SRodney W. Grimes if (*cp == 'c') { 310dea673e9SRodney W. Grimes n = 0; 311dea673e9SRodney W. Grimes while (i + 1 < nitems) { 312dea673e9SRodney W. Grimes cp1 = queue[i + 1]->d_name; 313dea673e9SRodney W. Grimes if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 314dea673e9SRodney W. Grimes break; 315dea673e9SRodney W. Grimes i++; 316dea673e9SRodney W. Grimes n++; 317dea673e9SRodney W. Grimes } 318dea673e9SRodney W. Grimes if (n == 0) { 31987751a84SWarner Losh strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 32087751a84SWarner Losh line[sizeof(line) - 1] = '\0'; 321dea673e9SRodney W. Grimes unlinkf(line); 322dea673e9SRodney W. Grimes } 323dea673e9SRodney W. Grimes } else { 324dea673e9SRodney W. Grimes /* 325dea673e9SRodney W. Grimes * Must be a df with no cf (otherwise, it would have 326dea673e9SRodney W. Grimes * been skipped above) or a tf file (which can always 327dea673e9SRodney W. Grimes * be removed). 328dea673e9SRodney W. Grimes */ 32987751a84SWarner Losh strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 33087751a84SWarner Losh line[sizeof(line) - 1] = '\0'; 331dea673e9SRodney W. Grimes unlinkf(line); 332dea673e9SRodney W. Grimes } 333dea673e9SRodney W. Grimes } while (++i < nitems); 334dea673e9SRodney W. Grimes } 335dea673e9SRodney W. Grimes 336dea673e9SRodney W. Grimes static void 337ba7a1ad7SGarance A Drosehn unlinkf(char *name) 338dea673e9SRodney W. Grimes { 339360d4ad5SWarner Losh seteuid(euid); 340dea673e9SRodney W. Grimes if (unlink(name) < 0) 341dea673e9SRodney W. Grimes printf("\tcannot remove %s\n", name); 342dea673e9SRodney W. Grimes else 343dea673e9SRodney W. Grimes printf("\tremoved %s\n", name); 344360d4ad5SWarner Losh seteuid(uid); 345dea673e9SRodney W. Grimes } 346dea673e9SRodney W. Grimes 347dea673e9SRodney W. Grimes /* 348dea673e9SRodney W. Grimes * Enable queuing to the printer (allow lpr's). 349dea673e9SRodney W. Grimes */ 350dea673e9SRodney W. Grimes void 351ba7a1ad7SGarance A Drosehn enable(struct printer *pp) 352dea673e9SRodney W. Grimes { 353dea673e9SRodney W. Grimes struct stat stbuf; 3544a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 355dea673e9SRodney W. Grimes 3564a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 3574a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 358dea673e9SRodney W. Grimes 359dea673e9SRodney W. Grimes /* 360dea673e9SRodney W. Grimes * Turn off the group execute bit of the lock file to enable queuing. 361dea673e9SRodney W. Grimes */ 362360d4ad5SWarner Losh seteuid(euid); 3634a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 3644a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode & ~LFM_QUEUE_DIS) < 0) 365dea673e9SRodney W. Grimes printf("\tcannot enable queuing\n"); 366dea673e9SRodney W. Grimes else 367dea673e9SRodney W. Grimes printf("\tqueuing enabled\n"); 368dea673e9SRodney W. Grimes } 369360d4ad5SWarner Losh seteuid(uid); 370dea673e9SRodney W. Grimes } 371dea673e9SRodney W. Grimes 372dea673e9SRodney W. Grimes /* 373dea673e9SRodney W. Grimes * Disable queuing. 374dea673e9SRodney W. Grimes */ 375dea673e9SRodney W. Grimes void 376ba7a1ad7SGarance A Drosehn disable(struct printer *pp) 377dea673e9SRodney W. Grimes { 378dea673e9SRodney W. Grimes register int fd; 379dea673e9SRodney W. Grimes struct stat stbuf; 3804a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 381dea673e9SRodney W. Grimes 3824a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 3834a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 384dea673e9SRodney W. Grimes /* 385dea673e9SRodney W. Grimes * Turn on the group execute bit of the lock file to disable queuing. 386dea673e9SRodney W. Grimes */ 387360d4ad5SWarner Losh seteuid(euid); 3884a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 3894a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_QUEUE_DIS) < 0) 3904a1a0dbeSGarrett Wollman printf("\tcannot disable queuing: %s\n", 3914a1a0dbeSGarrett Wollman strerror(errno)); 392dea673e9SRodney W. Grimes else 393dea673e9SRodney W. Grimes printf("\tqueuing disabled\n"); 394dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 3954a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 3964a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_QUEUE_DIS)) < 0) 3974a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 3984a1a0dbeSGarrett Wollman strerror(errno)); 399dea673e9SRodney W. Grimes else { 400dea673e9SRodney W. Grimes (void) close(fd); 401dea673e9SRodney W. Grimes printf("\tqueuing disabled\n"); 402dea673e9SRodney W. Grimes } 403dea673e9SRodney W. Grimes } else 404dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 405360d4ad5SWarner Losh seteuid(uid); 406dea673e9SRodney W. Grimes } 407dea673e9SRodney W. Grimes 408dea673e9SRodney W. Grimes /* 409dea673e9SRodney W. Grimes * Disable queuing and printing and put a message into the status file 410dea673e9SRodney W. Grimes * (reason for being down). 411dea673e9SRodney W. Grimes */ 412dea673e9SRodney W. Grimes void 413ba7a1ad7SGarance A Drosehn down(int argc, char *argv[]) 414dea673e9SRodney W. Grimes { 415ba7a1ad7SGarance A Drosehn int cmdstatus, more; 4164a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 417dea673e9SRodney W. Grimes 418dea673e9SRodney W. Grimes if (argc == 1) { 419dea673e9SRodney W. Grimes printf("Usage: down {all | printer} [message ...]\n"); 420dea673e9SRodney W. Grimes return; 421dea673e9SRodney W. Grimes } 422dea673e9SRodney W. Grimes if (!strcmp(argv[1], "all")) { 423ba7a1ad7SGarance A Drosehn more = firstprinter(pp, &cmdstatus); 424ba7a1ad7SGarance A Drosehn if (cmdstatus) 4254a1a0dbeSGarrett Wollman goto looperr; 4264a1a0dbeSGarrett Wollman while (more) { 4274a1a0dbeSGarrett Wollman putmsg(pp, argc - 2, argv + 2); 4284a1a0dbeSGarrett Wollman do { 429ba7a1ad7SGarance A Drosehn more = nextprinter(pp, &cmdstatus); 4304a1a0dbeSGarrett Wollman looperr: 431ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 4324a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 4334a1a0dbeSGarrett Wollman printf("warning: %s: unresolved " 4344a1a0dbeSGarrett Wollman "tc= reference(s) ", 4354a1a0dbeSGarrett Wollman pp->printer); 4364a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 4374a1a0dbeSGarrett Wollman break; 4384a1a0dbeSGarrett Wollman default: 439ba7a1ad7SGarance A Drosehn fatal(pp, pcaperr(cmdstatus)); 4404a1a0dbeSGarrett Wollman } 441ba7a1ad7SGarance A Drosehn } while (more && cmdstatus); 442dea673e9SRodney W. Grimes } 443dea673e9SRodney W. Grimes return; 444dea673e9SRodney W. Grimes } 4454a1a0dbeSGarrett Wollman init_printer(pp); 446ba7a1ad7SGarance A Drosehn cmdstatus = getprintcap(argv[1], pp); 447ba7a1ad7SGarance A Drosehn switch (cmdstatus) { 4484a1a0dbeSGarrett Wollman default: 449ba7a1ad7SGarance A Drosehn fatal(pp, pcaperr(cmdstatus)); 4504a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 4514a1a0dbeSGarrett Wollman printf("unknown printer %s\n", argv[1]); 452dea673e9SRodney W. Grimes return; 4534a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 4544a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)", argv[1]); 4554a1a0dbeSGarrett Wollman break; 4564a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 4574a1a0dbeSGarrett Wollman break; 4584a1a0dbeSGarrett Wollman } 4594a1a0dbeSGarrett Wollman putmsg(pp, argc - 2, argv + 2); 460dea673e9SRodney W. Grimes } 461dea673e9SRodney W. Grimes 462dea673e9SRodney W. Grimes static void 463ba7a1ad7SGarance A Drosehn putmsg(struct printer *pp, int argc, char **argv) 464dea673e9SRodney W. Grimes { 465dea673e9SRodney W. Grimes register int fd; 466dea673e9SRodney W. Grimes register char *cp1, *cp2; 467dea673e9SRodney W. Grimes char buf[1024]; 4684a1a0dbeSGarrett Wollman char file[MAXPATHLEN]; 469dea673e9SRodney W. Grimes struct stat stbuf; 470dea673e9SRodney W. Grimes 4714a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 472dea673e9SRodney W. Grimes /* 4734a1a0dbeSGarrett Wollman * Turn on the group execute bit of the lock file to disable queuing; 474dea673e9SRodney W. Grimes * turn on the owner execute bit of the lock file to disable printing. 475dea673e9SRodney W. Grimes */ 4764a1a0dbeSGarrett Wollman lock_file_name(pp, file, sizeof file); 477360d4ad5SWarner Losh seteuid(euid); 4784a1a0dbeSGarrett Wollman if (stat(file, &stbuf) >= 0) { 4794a1a0dbeSGarrett Wollman if (chmod(file, stbuf.st_mode|LFM_PRINT_DIS|LFM_QUEUE_DIS) < 0) 4804a1a0dbeSGarrett Wollman printf("\tcannot disable queuing: %s\n", 4814a1a0dbeSGarrett Wollman strerror(errno)); 482dea673e9SRodney W. Grimes else 483dea673e9SRodney W. Grimes printf("\tprinter and queuing disabled\n"); 484dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 4854a1a0dbeSGarrett Wollman if ((fd = open(file, O_WRONLY|O_CREAT, 4864a1a0dbeSGarrett Wollman LOCK_FILE_MODE|LFM_PRINT_DIS|LFM_QUEUE_DIS)) < 0) 4874a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 4884a1a0dbeSGarrett Wollman strerror(errno)); 489dea673e9SRodney W. Grimes else { 490dea673e9SRodney W. Grimes (void) close(fd); 491dea673e9SRodney W. Grimes printf("\tprinter and queuing disabled\n"); 492dea673e9SRodney W. Grimes } 493360d4ad5SWarner Losh seteuid(uid); 494dea673e9SRodney W. Grimes return; 495dea673e9SRodney W. Grimes } else 496dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 497dea673e9SRodney W. Grimes /* 498dea673e9SRodney W. Grimes * Write the message into the status file. 499dea673e9SRodney W. Grimes */ 5004a1a0dbeSGarrett Wollman status_file_name(pp, file, sizeof file); 5014a1a0dbeSGarrett Wollman fd = open(file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 5024a1a0dbeSGarrett Wollman if (fd < 0) { 5034a1a0dbeSGarrett Wollman printf("\tcannot create status file: %s\n", strerror(errno)); 504360d4ad5SWarner Losh seteuid(uid); 505dea673e9SRodney W. Grimes return; 506dea673e9SRodney W. Grimes } 507360d4ad5SWarner Losh seteuid(uid); 508dea673e9SRodney W. Grimes (void) ftruncate(fd, 0); 509dea673e9SRodney W. Grimes if (argc <= 0) { 510dea673e9SRodney W. Grimes (void) write(fd, "\n", 1); 511dea673e9SRodney W. Grimes (void) close(fd); 512dea673e9SRodney W. Grimes return; 513dea673e9SRodney W. Grimes } 514dea673e9SRodney W. Grimes cp1 = buf; 515dea673e9SRodney W. Grimes while (--argc >= 0) { 516dea673e9SRodney W. Grimes cp2 = *argv++; 5175f87a7b6SWarner Losh while ((cp1 - buf) < sizeof(buf) && (*cp1++ = *cp2++)) 518dea673e9SRodney W. Grimes ; 519dea673e9SRodney W. Grimes cp1[-1] = ' '; 520dea673e9SRodney W. Grimes } 521dea673e9SRodney W. Grimes cp1[-1] = '\n'; 522dea673e9SRodney W. Grimes *cp1 = '\0'; 523dea673e9SRodney W. Grimes (void) write(fd, buf, strlen(buf)); 524dea673e9SRodney W. Grimes (void) close(fd); 525dea673e9SRodney W. Grimes } 526dea673e9SRodney W. Grimes 527dea673e9SRodney W. Grimes /* 528dea673e9SRodney W. Grimes * Exit lpc 529dea673e9SRodney W. Grimes */ 530dea673e9SRodney W. Grimes void 531ba7a1ad7SGarance A Drosehn quit(int argc __unused, char *argv[] __unused) 532dea673e9SRodney W. Grimes { 533dea673e9SRodney W. Grimes exit(0); 534dea673e9SRodney W. Grimes } 535dea673e9SRodney W. Grimes 536dea673e9SRodney W. Grimes /* 537dea673e9SRodney W. Grimes * Kill and restart the daemon. 538dea673e9SRodney W. Grimes */ 539dea673e9SRodney W. Grimes void 540ba7a1ad7SGarance A Drosehn restart(struct printer *pp) 541dea673e9SRodney W. Grimes { 5424a1a0dbeSGarrett Wollman abortpr(pp, 0); 5434a1a0dbeSGarrett Wollman startpr(pp, 0); 544dea673e9SRodney W. Grimes } 545dea673e9SRodney W. Grimes 546dea673e9SRodney W. Grimes /* 547dea673e9SRodney W. Grimes * Enable printing on the specified printer and startup the daemon. 548dea673e9SRodney W. Grimes */ 549dea673e9SRodney W. Grimes void 550ba7a1ad7SGarance A Drosehn startcmd(struct printer *pp) 551dea673e9SRodney W. Grimes { 5524a1a0dbeSGarrett Wollman startpr(pp, 1); 553dea673e9SRodney W. Grimes } 554dea673e9SRodney W. Grimes 555dea673e9SRodney W. Grimes static void 556ba7a1ad7SGarance A Drosehn startpr(struct printer *pp, int chgenable) 557dea673e9SRodney W. Grimes { 558dea673e9SRodney W. Grimes struct stat stbuf; 5594a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 560dea673e9SRodney W. Grimes 5614a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 5624a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 563dea673e9SRodney W. Grimes 564dea673e9SRodney W. Grimes /* 565ba7a1ad7SGarance A Drosehn * For chgenable==1 ('start'), turn off the LFM_PRINT_DIS bit of the 566ba7a1ad7SGarance A Drosehn * lock file to re-enable printing. For chgenable==2 ('up'), also 5671bd87e1bSMatthew Dillon * turn off the LFM_QUEUE_DIS bit to re-enable queueing. 568dea673e9SRodney W. Grimes */ 569360d4ad5SWarner Losh seteuid(euid); 570ba7a1ad7SGarance A Drosehn if (chgenable && stat(lf, &stbuf) >= 0) { 571ba7a1ad7SGarance A Drosehn mode_t bits = (chgenable == 2 ? 0 : LFM_QUEUE_DIS); 5724a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode & (LOCK_FILE_MODE | bits)) < 0) 573dea673e9SRodney W. Grimes printf("\tcannot enable printing\n"); 574dea673e9SRodney W. Grimes else 575dea673e9SRodney W. Grimes printf("\tprinting enabled\n"); 576dea673e9SRodney W. Grimes } 5774a1a0dbeSGarrett Wollman if (!startdaemon(pp)) 578dea673e9SRodney W. Grimes printf("\tcouldn't start daemon\n"); 579dea673e9SRodney W. Grimes else 580dea673e9SRodney W. Grimes printf("\tdaemon started\n"); 581360d4ad5SWarner Losh seteuid(uid); 582dea673e9SRodney W. Grimes } 583dea673e9SRodney W. Grimes 584dea673e9SRodney W. Grimes /* 585dea673e9SRodney W. Grimes * Print the status of the printer queue. 586dea673e9SRodney W. Grimes */ 5874a1a0dbeSGarrett Wollman void 588ba7a1ad7SGarance A Drosehn status(struct printer *pp) 589dea673e9SRodney W. Grimes { 590dea673e9SRodney W. Grimes struct stat stbuf; 591dea673e9SRodney W. Grimes register int fd, i; 592dea673e9SRodney W. Grimes register struct dirent *dp; 593dea673e9SRodney W. Grimes DIR *dirp; 5944a1a0dbeSGarrett Wollman char file[MAXPATHLEN]; 595dea673e9SRodney W. Grimes 5964a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 5974a1a0dbeSGarrett Wollman lock_file_name(pp, file, sizeof file); 5984a1a0dbeSGarrett Wollman if (stat(file, &stbuf) >= 0) { 599dea673e9SRodney W. Grimes printf("\tqueuing is %s\n", 6004a1a0dbeSGarrett Wollman ((stbuf.st_mode & LFM_QUEUE_DIS) ? "disabled" 6014a1a0dbeSGarrett Wollman : "enabled")); 602dea673e9SRodney W. Grimes printf("\tprinting is %s\n", 6034a1a0dbeSGarrett Wollman ((stbuf.st_mode & LFM_PRINT_DIS) ? "disabled" 6044a1a0dbeSGarrett Wollman : "enabled")); 605dea673e9SRodney W. Grimes } else { 606dea673e9SRodney W. Grimes printf("\tqueuing is enabled\n"); 607dea673e9SRodney W. Grimes printf("\tprinting is enabled\n"); 608dea673e9SRodney W. Grimes } 6094a1a0dbeSGarrett Wollman if ((dirp = opendir(pp->spool_dir)) == NULL) { 610dea673e9SRodney W. Grimes printf("\tcannot examine spool directory\n"); 611dea673e9SRodney W. Grimes return; 612dea673e9SRodney W. Grimes } 613dea673e9SRodney W. Grimes i = 0; 614dea673e9SRodney W. Grimes while ((dp = readdir(dirp)) != NULL) { 615dea673e9SRodney W. Grimes if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 616dea673e9SRodney W. Grimes i++; 617dea673e9SRodney W. Grimes } 618dea673e9SRodney W. Grimes closedir(dirp); 619dea673e9SRodney W. Grimes if (i == 0) 6204a1a0dbeSGarrett Wollman printf("\tno entries in spool area\n"); 621dea673e9SRodney W. Grimes else if (i == 1) 622dea673e9SRodney W. Grimes printf("\t1 entry in spool area\n"); 623dea673e9SRodney W. Grimes else 624dea673e9SRodney W. Grimes printf("\t%d entries in spool area\n", i); 6254a1a0dbeSGarrett Wollman fd = open(file, O_RDONLY); 626dea673e9SRodney W. Grimes if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 627dea673e9SRodney W. Grimes (void) close(fd); /* unlocks as well */ 628bc407914SWarner Losh printf("\tprinter idle\n"); 629dea673e9SRodney W. Grimes return; 630dea673e9SRodney W. Grimes } 631dea673e9SRodney W. Grimes (void) close(fd); 63236abea5dSBrian Somers /* print out the contents of the status file, if it exists */ 6334a1a0dbeSGarrett Wollman status_file_name(pp, file, sizeof file); 6344a1a0dbeSGarrett Wollman fd = open(file, O_RDONLY|O_SHLOCK); 635dea673e9SRodney W. Grimes if (fd >= 0) { 63636abea5dSBrian Somers (void) fstat(fd, &stbuf); 63736abea5dSBrian Somers if (stbuf.st_size > 0) { 63836abea5dSBrian Somers putchar('\t'); 639dea673e9SRodney W. Grimes while ((i = read(fd, line, sizeof(line))) > 0) 640dea673e9SRodney W. Grimes (void) fwrite(line, 1, i, stdout); 64136abea5dSBrian Somers } 642dea673e9SRodney W. Grimes (void) close(fd); /* unlocks as well */ 643dea673e9SRodney W. Grimes } 644dea673e9SRodney W. Grimes } 645dea673e9SRodney W. Grimes 646dea673e9SRodney W. Grimes /* 647dea673e9SRodney W. Grimes * Stop the specified daemon after completing the current job and disable 648dea673e9SRodney W. Grimes * printing. 649dea673e9SRodney W. Grimes */ 650dea673e9SRodney W. Grimes void 651ba7a1ad7SGarance A Drosehn stop(struct printer *pp) 652dea673e9SRodney W. Grimes { 653dea673e9SRodney W. Grimes register int fd; 654dea673e9SRodney W. Grimes struct stat stbuf; 6554a1a0dbeSGarrett Wollman char lf[MAXPATHLEN]; 656dea673e9SRodney W. Grimes 6574a1a0dbeSGarrett Wollman lock_file_name(pp, lf, sizeof lf); 6584a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 659dea673e9SRodney W. Grimes 660dea673e9SRodney W. Grimes /* 661dea673e9SRodney W. Grimes * Turn on the owner execute bit of the lock file to disable printing. 662dea673e9SRodney W. Grimes */ 663360d4ad5SWarner Losh seteuid(euid); 6644a1a0dbeSGarrett Wollman if (stat(lf, &stbuf) >= 0) { 6654a1a0dbeSGarrett Wollman if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 6664a1a0dbeSGarrett Wollman printf("\tcannot disable printing: %s\n", 6674a1a0dbeSGarrett Wollman strerror(errno)); 668dea673e9SRodney W. Grimes else { 6694a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 670dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 671dea673e9SRodney W. Grimes } 672dea673e9SRodney W. Grimes } else if (errno == ENOENT) { 6734a1a0dbeSGarrett Wollman if ((fd = open(lf, O_WRONLY|O_CREAT, 6744a1a0dbeSGarrett Wollman LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 6754a1a0dbeSGarrett Wollman printf("\tcannot create lock file: %s\n", 6764a1a0dbeSGarrett Wollman strerror(errno)); 677dea673e9SRodney W. Grimes else { 678dea673e9SRodney W. Grimes (void) close(fd); 6794a1a0dbeSGarrett Wollman upstat(pp, "printing disabled\n"); 680dea673e9SRodney W. Grimes printf("\tprinting disabled\n"); 681dea673e9SRodney W. Grimes } 682dea673e9SRodney W. Grimes } else 683dea673e9SRodney W. Grimes printf("\tcannot stat lock file\n"); 684360d4ad5SWarner Losh seteuid(uid); 685dea673e9SRodney W. Grimes } 686dea673e9SRodney W. Grimes 68730b4b758SGarance A Drosehn struct jobqueue **queue; 688dea673e9SRodney W. Grimes int nitems; 689dea673e9SRodney W. Grimes time_t mtime; 690dea673e9SRodney W. Grimes 691dea673e9SRodney W. Grimes /* 692dea673e9SRodney W. Grimes * Put the specified jobs at the top of printer queue. 693dea673e9SRodney W. Grimes */ 694dea673e9SRodney W. Grimes void 695ba7a1ad7SGarance A Drosehn topq(int argc, char *argv[]) 696dea673e9SRodney W. Grimes { 697dea673e9SRodney W. Grimes register int i; 698dea673e9SRodney W. Grimes struct stat stbuf; 699ba7a1ad7SGarance A Drosehn int cmdstatus, changed; 7004a1a0dbeSGarrett Wollman struct printer myprinter, *pp = &myprinter; 701dea673e9SRodney W. Grimes 702dea673e9SRodney W. Grimes if (argc < 3) { 703dea673e9SRodney W. Grimes printf("Usage: topq printer [jobnum ...] [user ...]\n"); 704dea673e9SRodney W. Grimes return; 705dea673e9SRodney W. Grimes } 706dea673e9SRodney W. Grimes 707dea673e9SRodney W. Grimes --argc; 7084a1a0dbeSGarrett Wollman ++argv; 7094a1a0dbeSGarrett Wollman init_printer(pp); 710ba7a1ad7SGarance A Drosehn cmdstatus = getprintcap(*argv, pp); 711ba7a1ad7SGarance A Drosehn switch(cmdstatus) { 7124a1a0dbeSGarrett Wollman default: 713ba7a1ad7SGarance A Drosehn fatal(pp, pcaperr(cmdstatus)); 7144a1a0dbeSGarrett Wollman case PCAPERR_NOTFOUND: 7154a1a0dbeSGarrett Wollman printf("unknown printer %s\n", *argv); 716dea673e9SRodney W. Grimes return; 7174a1a0dbeSGarrett Wollman case PCAPERR_TCOPEN: 7184a1a0dbeSGarrett Wollman printf("warning: %s: unresolved tc= reference(s)", *argv); 7194a1a0dbeSGarrett Wollman break; 7204a1a0dbeSGarrett Wollman case PCAPERR_SUCCESS: 7214a1a0dbeSGarrett Wollman break; 7224a1a0dbeSGarrett Wollman } 7234a1a0dbeSGarrett Wollman printf("%s:\n", pp->printer); 724dea673e9SRodney W. Grimes 725360d4ad5SWarner Losh seteuid(euid); 7264a1a0dbeSGarrett Wollman if (chdir(pp->spool_dir) < 0) { 7274a1a0dbeSGarrett Wollman printf("\tcannot chdir to %s\n", pp->spool_dir); 728360d4ad5SWarner Losh goto out; 729dea673e9SRodney W. Grimes } 730360d4ad5SWarner Losh seteuid(uid); 7314a1a0dbeSGarrett Wollman nitems = getq(pp, &queue); 732dea673e9SRodney W. Grimes if (nitems == 0) 733dea673e9SRodney W. Grimes return; 734dea673e9SRodney W. Grimes changed = 0; 73530b4b758SGarance A Drosehn mtime = queue[0]->job_time; 736dea673e9SRodney W. Grimes for (i = argc; --i; ) { 737dea673e9SRodney W. Grimes if (doarg(argv[i]) == 0) { 738dea673e9SRodney W. Grimes printf("\tjob %s is not in the queue\n", argv[i]); 739dea673e9SRodney W. Grimes continue; 740dea673e9SRodney W. Grimes } else 741dea673e9SRodney W. Grimes changed++; 742dea673e9SRodney W. Grimes } 743dea673e9SRodney W. Grimes for (i = 0; i < nitems; i++) 744dea673e9SRodney W. Grimes free(queue[i]); 745dea673e9SRodney W. Grimes free(queue); 746dea673e9SRodney W. Grimes if (!changed) { 747dea673e9SRodney W. Grimes printf("\tqueue order unchanged\n"); 748dea673e9SRodney W. Grimes return; 749dea673e9SRodney W. Grimes } 750dea673e9SRodney W. Grimes /* 751dea673e9SRodney W. Grimes * Turn on the public execute bit of the lock file to 752dea673e9SRodney W. Grimes * get lpd to rebuild the queue after the current job. 753dea673e9SRodney W. Grimes */ 754360d4ad5SWarner Losh seteuid(euid); 7554a1a0dbeSGarrett Wollman if (changed && stat(pp->lock_file, &stbuf) >= 0) 7564a1a0dbeSGarrett Wollman (void) chmod(pp->lock_file, stbuf.st_mode | LFM_RESET_QUE); 757360d4ad5SWarner Losh 758360d4ad5SWarner Losh out: 759360d4ad5SWarner Losh seteuid(uid); 760dea673e9SRodney W. Grimes } 761dea673e9SRodney W. Grimes 762dea673e9SRodney W. Grimes /* 763dea673e9SRodney W. Grimes * Reposition the job by changing the modification time of 764dea673e9SRodney W. Grimes * the control file. 765dea673e9SRodney W. Grimes */ 766dea673e9SRodney W. Grimes static int 767ba7a1ad7SGarance A Drosehn touch(struct jobqueue *jq) 768dea673e9SRodney W. Grimes { 769dea673e9SRodney W. Grimes struct timeval tvp[2]; 770360d4ad5SWarner Losh int ret; 771dea673e9SRodney W. Grimes 772dea673e9SRodney W. Grimes tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 773dea673e9SRodney W. Grimes tvp[0].tv_usec = tvp[1].tv_usec = 0; 774360d4ad5SWarner Losh seteuid(euid); 775ba7a1ad7SGarance A Drosehn ret = utimes(jq->job_cfname, tvp); 776360d4ad5SWarner Losh seteuid(uid); 777360d4ad5SWarner Losh return (ret); 778dea673e9SRodney W. Grimes } 779dea673e9SRodney W. Grimes 780dea673e9SRodney W. Grimes /* 781dea673e9SRodney W. Grimes * Checks if specified job name is in the printer's queue. 782dea673e9SRodney W. Grimes * Returns: negative (-1) if argument name is not in the queue. 783dea673e9SRodney W. Grimes */ 784dea673e9SRodney W. Grimes static int 785ba7a1ad7SGarance A Drosehn doarg(char *job) 786dea673e9SRodney W. Grimes { 78730b4b758SGarance A Drosehn register struct jobqueue **qq; 788dea673e9SRodney W. Grimes register int jobnum, n; 789dea673e9SRodney W. Grimes register char *cp, *machine; 790dea673e9SRodney W. Grimes int cnt = 0; 791dea673e9SRodney W. Grimes FILE *fp; 792dea673e9SRodney W. Grimes 793dea673e9SRodney W. Grimes /* 794dea673e9SRodney W. Grimes * Look for a job item consisting of system name, colon, number 795dea673e9SRodney W. Grimes * (example: ucbarpa:114) 796dea673e9SRodney W. Grimes */ 797f8eb25daSWarner Losh if ((cp = strchr(job, ':')) != NULL) { 798dea673e9SRodney W. Grimes machine = job; 799dea673e9SRodney W. Grimes *cp++ = '\0'; 800dea673e9SRodney W. Grimes job = cp; 801dea673e9SRodney W. Grimes } else 802dea673e9SRodney W. Grimes machine = NULL; 803dea673e9SRodney W. Grimes 804dea673e9SRodney W. Grimes /* 805dea673e9SRodney W. Grimes * Check for job specified by number (example: 112 or 235ucbarpa). 806dea673e9SRodney W. Grimes */ 807dea673e9SRodney W. Grimes if (isdigit(*job)) { 808dea673e9SRodney W. Grimes jobnum = 0; 809dea673e9SRodney W. Grimes do 810dea673e9SRodney W. Grimes jobnum = jobnum * 10 + (*job++ - '0'); 811dea673e9SRodney W. Grimes while (isdigit(*job)); 812dea673e9SRodney W. Grimes for (qq = queue + nitems; --qq >= queue; ) { 813dea673e9SRodney W. Grimes n = 0; 81430b4b758SGarance A Drosehn for (cp = (*qq)->job_cfname+3; isdigit(*cp); ) 815dea673e9SRodney W. Grimes n = n * 10 + (*cp++ - '0'); 816dea673e9SRodney W. Grimes if (jobnum != n) 817dea673e9SRodney W. Grimes continue; 818dea673e9SRodney W. Grimes if (*job && strcmp(job, cp) != 0) 819dea673e9SRodney W. Grimes continue; 820dea673e9SRodney W. Grimes if (machine != NULL && strcmp(machine, cp) != 0) 821dea673e9SRodney W. Grimes continue; 822dea673e9SRodney W. Grimes if (touch(*qq) == 0) { 82330b4b758SGarance A Drosehn printf("\tmoved %s\n", (*qq)->job_cfname); 824dea673e9SRodney W. Grimes cnt++; 825dea673e9SRodney W. Grimes } 826dea673e9SRodney W. Grimes } 827dea673e9SRodney W. Grimes return(cnt); 828dea673e9SRodney W. Grimes } 829dea673e9SRodney W. Grimes /* 830dea673e9SRodney W. Grimes * Process item consisting of owner's name (example: henry). 831dea673e9SRodney W. Grimes */ 832dea673e9SRodney W. Grimes for (qq = queue + nitems; --qq >= queue; ) { 833360d4ad5SWarner Losh seteuid(euid); 83430b4b758SGarance A Drosehn fp = fopen((*qq)->job_cfname, "r"); 835360d4ad5SWarner Losh seteuid(uid); 836360d4ad5SWarner Losh if (fp == NULL) 837dea673e9SRodney W. Grimes continue; 838dea673e9SRodney W. Grimes while (getline(fp) > 0) 839dea673e9SRodney W. Grimes if (line[0] == 'P') 840dea673e9SRodney W. Grimes break; 841dea673e9SRodney W. Grimes (void) fclose(fp); 842dea673e9SRodney W. Grimes if (line[0] != 'P' || strcmp(job, line+1) != 0) 843dea673e9SRodney W. Grimes continue; 844dea673e9SRodney W. Grimes if (touch(*qq) == 0) { 84530b4b758SGarance A Drosehn printf("\tmoved %s\n", (*qq)->job_cfname); 846dea673e9SRodney W. Grimes cnt++; 847dea673e9SRodney W. Grimes } 848dea673e9SRodney W. Grimes } 849dea673e9SRodney W. Grimes return(cnt); 850dea673e9SRodney W. Grimes } 851dea673e9SRodney W. Grimes 852dea673e9SRodney W. Grimes /* 853dea673e9SRodney W. Grimes * Enable everything and start printer (undo `down'). 854dea673e9SRodney W. Grimes */ 855dea673e9SRodney W. Grimes void 856ba7a1ad7SGarance A Drosehn up(struct printer *pp) 857dea673e9SRodney W. Grimes { 8584a1a0dbeSGarrett Wollman startpr(pp, 2); 859dea673e9SRodney W. Grimes } 860