diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
commit | 862fdf11a2ede45dec0da01ed575525d79468981 (patch) | |
tree | 7a1c88ccb8006476bd4b4a548a6ad48fbfc33a01 /usr.sbin/lpr/lpc | |
parent | 8e1a19ddde0df113b0b26b0ea621afd61dbaf91f (diff) | |
download | FreeBSD-src-862fdf11a2ede45dec0da01ed575525d79468981.zip FreeBSD-src-862fdf11a2ede45dec0da01ed575525d79468981.tar.gz |
BSD 4.4 Lite usr.sbin Sources
Diffstat (limited to 'usr.sbin/lpr/lpc')
-rw-r--r-- | usr.sbin/lpr/lpc/Makefile | 12 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/cmds.c | 1107 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/cmdtab.c | 79 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/extern.h | 58 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/lpc.8 | 174 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/lpc.c | 277 | ||||
-rw-r--r-- | usr.sbin/lpr/lpc/lpc.h | 45 |
7 files changed, 1752 insertions, 0 deletions
diff --git a/usr.sbin/lpr/lpc/Makefile b/usr.sbin/lpr/lpc/Makefile new file mode 100644 index 0000000..10a3d69 --- /dev/null +++ b/usr.sbin/lpr/lpc/Makefile @@ -0,0 +1,12 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lpc +CFLAGS+=-I${.CURDIR}/../common_source +MAN8= lpc.0 +SRCS= lpc.c cmds.c cmdtab.c startdaemon.c common.c +BINGRP= daemon +BINMODE=2555 +.PATH: ${.CURDIR}/../common_source + +.include "../../Makefile.inc" +.include <bsd.prog.mk> diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c new file mode 100644 index 0000000..7c2b6fe --- /dev/null +++ b/usr.sbin/lpr/lpc/cmds.c @@ -0,0 +1,1107 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * lpc -- line printer control program -- commands: + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/stat.h> + +#include <signal.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include "lp.h" +#include "lp.local.h" +#include "lpc.h" +#include "extern.h" +#include "pathnames.h" + +static void abortpr __P((int)); +static void cleanpr __P((void)); +static void disablepr __P((void)); +static int doarg __P((char *)); +static int doselect __P((struct dirent *)); +static void enablepr __P((void)); +static void prstat __P((void)); +static void putmsg __P((int, char **)); +static int sortq __P((const void *, const void *)); +static void startpr __P((int)); +static void stoppr __P((void)); +static int touch __P((struct queue *)); +static void unlinkf __P((char *)); +static void upstat __P((char *)); + +/* + * kill an existing daemon and disable printing. + */ +void +doabort(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: abort {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + abortpr(1); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + abortpr(1); + } +} + +static void +abortpr(dis) + int dis; +{ + register FILE *fp; + struct stat stbuf; + int pid, fd; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn on the owner execute bit of the lock file to disable printing. + */ + if (dis) { + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) + printf("\tcannot disable printing\n"); + else { + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + } + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + printf("\tno daemon to abort\n"); + } + return; + } else { + printf("\tcannot stat lock file\n"); + return; + } + } + /* + * Kill the current daemon to stop printing now. + */ + if ((fp = fopen(line, "r")) == NULL) { + printf("\tcannot open lock file\n"); + return; + } + if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { + (void) fclose(fp); /* unlocks as well */ + printf("\tno daemon to abort\n"); + return; + } + (void) fclose(fp); + if (kill(pid = atoi(line), SIGTERM) < 0) + printf("\tWarning: daemon (pid %d) not killed\n", pid); + else + printf("\tdaemon (pid %d) killed\n", pid); +} + +/* + * Write a message into the status file. + */ +static void +upstat(msg) + char *msg; +{ + register int fd; + char statfile[BUFSIZ]; + + if (cgetstr(bp, "st", &ST) == -1) + ST = DEFSTAT; + (void) sprintf(statfile, "%s/%s", SD, ST); + umask(0); + fd = open(statfile, O_WRONLY|O_CREAT, 0664); + if (fd < 0 || flock(fd, LOCK_EX) < 0) { + printf("\tcannot create status file\n"); + return; + } + (void) ftruncate(fd, 0); + if (msg == (char *)NULL) + (void) write(fd, "\n", 1); + else + (void) write(fd, msg, strlen(msg)); + (void) close(fd); +} + +/* + * Remove all spool files and temporaries from the spooling area. + */ +void +clean(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: clean {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + cleanpr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + cleanpr(); + } +} + +static int +doselect(d) + struct dirent *d; +{ + int c = d->d_name[0]; + + if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') + return(1); + return(0); +} + +/* + * Comparison routine for scandir. Sort by job number and machine, then + * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. + */ +static int +sortq(a, b) + const void *a, *b; +{ + struct dirent **d1, **d2; + int c1, c2; + + d1 = (struct dirent **)a; + d2 = (struct dirent **)b; + if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) + return(c1); + c1 = (*d1)->d_name[0]; + c2 = (*d2)->d_name[0]; + if (c1 == c2) + return((*d1)->d_name[2] - (*d2)->d_name[2]); + if (c1 == 'c') + return(-1); + if (c1 == 'd' || c2 == 'c') + return(1); + return(-1); +} + +/* + * Remove incomplete jobs from spooling area. + */ +static void +cleanpr() +{ + register int i, n; + register char *cp, *cp1, *lp; + struct dirent **queue; + int nitems; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + printf("%s:\n", printer); + + for (lp = line, cp = SD; *lp++ = *cp++; ) + ; + lp[-1] = '/'; + + nitems = scandir(SD, &queue, doselect, sortq); + if (nitems < 0) { + printf("\tcannot examine spool directory\n"); + return; + } + if (nitems == 0) + return; + i = 0; + do { + cp = queue[i]->d_name; + if (*cp == 'c') { + n = 0; + while (i + 1 < nitems) { + cp1 = queue[i + 1]->d_name; + if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) + break; + i++; + n++; + } + if (n == 0) { + strcpy(lp, cp); + unlinkf(line); + } + } else { + /* + * Must be a df with no cf (otherwise, it would have + * been skipped above) or a tf file (which can always + * be removed). + */ + strcpy(lp, cp); + unlinkf(line); + } + } while (++i < nitems); +} + +static void +unlinkf(name) + char *name; +{ + if (unlink(name) < 0) + printf("\tcannot remove %s\n", name); + else + printf("\tremoved %s\n", name); +} + +/* + * Enable queuing to the printer (allow lpr's). + */ +void +enable(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: enable {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + enablepr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + enablepr(); + } +} + +static void +enablepr() +{ + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn off the group execute bit of the lock file to enable queuing. + */ + if (stat(line, &stbuf) >= 0) { + if (chmod(line, stbuf.st_mode & 0767) < 0) + printf("\tcannot enable queuing\n"); + else + printf("\tqueuing enabled\n"); + } +} + +/* + * Disable queuing. + */ +void +disable(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: disable {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + disablepr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + disablepr(); + } +} + +static void +disablepr() +{ + register int fd; + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + /* + * Turn on the group execute bit of the lock file to disable queuing. + */ + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) + printf("\tcannot disable queuing\n"); + else + printf("\tqueuing disabled\n"); + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + printf("\tqueuing disabled\n"); + } + return; + } else + printf("\tcannot stat lock file\n"); +} + +/* + * Disable queuing and printing and put a message into the status file + * (reason for being down). + */ +void +down(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: down {all | printer} [message ...]\n"); + return; + } + if (!strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + putmsg(argc - 2, argv + 2); + } + return; + } + printer = argv[1]; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + return; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + return; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + putmsg(argc - 2, argv + 2); +} + +static void +putmsg(argc, argv) + int argc; + char **argv; +{ + register int fd; + register char *cp1, *cp2; + char buf[1024]; + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + if (cgetstr(bp, "st", &ST) == -1) + ST = DEFSTAT; + printf("%s:\n", printer); + /* + * Turn on the group execute bit of the lock file to disable queuing and + * turn on the owner execute bit of the lock file to disable printing. + */ + (void) sprintf(line, "%s/%s", SD, LO); + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0) + printf("\tcannot disable queuing\n"); + else + printf("\tprinter and queuing disabled\n"); + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + printf("\tprinter and queuing disabled\n"); + } + return; + } else + printf("\tcannot stat lock file\n"); + /* + * Write the message into the status file. + */ + (void) sprintf(line, "%s/%s", SD, ST); + fd = open(line, O_WRONLY|O_CREAT, 0664); + if (fd < 0 || flock(fd, LOCK_EX) < 0) { + printf("\tcannot create status file\n"); + return; + } + (void) ftruncate(fd, 0); + if (argc <= 0) { + (void) write(fd, "\n", 1); + (void) close(fd); + return; + } + cp1 = buf; + while (--argc >= 0) { + cp2 = *argv++; + while (*cp1++ = *cp2++) + ; + cp1[-1] = ' '; + } + cp1[-1] = '\n'; + *cp1 = '\0'; + (void) write(fd, buf, strlen(buf)); + (void) close(fd); +} + +/* + * Exit lpc + */ +void +quit(argc, argv) + int argc; + char *argv[]; +{ + exit(0); +} + +/* + * Kill and restart the daemon. + */ +void +restart(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: restart {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + abortpr(0); + startpr(0); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + abortpr(0); + startpr(0); + } +} + +/* + * Enable printing on the specified printer and startup the daemon. + */ +void +startcmd(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: start {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + startpr(1); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + startpr(1); + } +} + +static void +startpr(enable) + int enable; +{ + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn off the owner execute bit of the lock file to enable printing. + */ + if (enable && stat(line, &stbuf) >= 0) { + if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0) + printf("\tcannot enable printing\n"); + else + printf("\tprinting enabled\n"); + } + if (!startdaemon(printer)) + printf("\tcouldn't start daemon\n"); + else + printf("\tdaemon started\n"); +} + +/* + * Print the status of each queue listed or all the queues. + */ +void +status(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + prstat(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + prstat(); + } +} + +/* + * Print the status of the printer queue. + */ +static void +prstat() +{ + struct stat stbuf; + register int fd, i; + register struct dirent *dp; + DIR *dirp; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + if (cgetstr(bp, "st", &ST) == -1) + ST = DEFSTAT; + printf("%s:\n", printer); + (void) sprintf(line, "%s/%s", SD, LO); + if (stat(line, &stbuf) >= 0) { + printf("\tqueuing is %s\n", + (stbuf.st_mode & 010) ? "disabled" : "enabled"); + printf("\tprinting is %s\n", + (stbuf.st_mode & 0100) ? "disabled" : "enabled"); + } else { + printf("\tqueuing is enabled\n"); + printf("\tprinting is enabled\n"); + } + if ((dirp = opendir(SD)) == NULL) { + printf("\tcannot examine spool directory\n"); + return; + } + i = 0; + while ((dp = readdir(dirp)) != NULL) { + if (*dp->d_name == 'c' && dp->d_name[1] == 'f') + i++; + } + closedir(dirp); + if (i == 0) + printf("\tno entries\n"); + else if (i == 1) + printf("\t1 entry in spool area\n"); + else + printf("\t%d entries in spool area\n", i); + fd = open(line, O_RDONLY); + if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { + (void) close(fd); /* unlocks as well */ + printf("\tno daemon present\n"); + return; + } + (void) close(fd); + putchar('\t'); + (void) sprintf(line, "%s/%s", SD, ST); + fd = open(line, O_RDONLY); + if (fd >= 0) { + (void) flock(fd, LOCK_SH); + while ((i = read(fd, line, sizeof(line))) > 0) + (void) fwrite(line, 1, i, stdout); + (void) close(fd); /* unlocks as well */ + } +} + +/* + * Stop the specified daemon after completing the current job and disable + * printing. + */ +void +stop(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: stop {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + stoppr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + stoppr(); + } +} + +static void +stoppr() +{ + register int fd; + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn on the owner execute bit of the lock file to disable printing. + */ + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) + printf("\tcannot disable printing\n"); + else { + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + } + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + } + } else + printf("\tcannot stat lock file\n"); +} + +struct queue **queue; +int nitems; +time_t mtime; + +/* + * Put the specified jobs at the top of printer queue. + */ +void +topq(argc, argv) + int argc; + char *argv[]; +{ + register int i; + struct stat stbuf; + int status, changed; + + if (argc < 3) { + printf("Usage: topq printer [jobnum ...] [user ...]\n"); + return; + } + + --argc; + printer = *++argv; + status = cgetent(&bp, printcapdb, printer); + if (status == -2) { + printf("cannot open printer description file\n"); + return; + } else if (status == -1) { + printf("%s: unknown printer\n", printer); + return; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + printf("%s:\n", printer); + + if (chdir(SD) < 0) { + printf("\tcannot chdir to %s\n", SD); + return; + } + nitems = getq(&queue); + if (nitems == 0) + return; + changed = 0; + mtime = queue[0]->q_time; + for (i = argc; --i; ) { + if (doarg(argv[i]) == 0) { + printf("\tjob %s is not in the queue\n", argv[i]); + continue; + } else + changed++; + } + for (i = 0; i < nitems; i++) + free(queue[i]); + free(queue); + if (!changed) { + printf("\tqueue order unchanged\n"); + return; + } + /* + * Turn on the public execute bit of the lock file to + * get lpd to rebuild the queue after the current job. + */ + if (changed && stat(LO, &stbuf) >= 0) + (void) chmod(LO, (stbuf.st_mode & 0777) | 01); +} + +/* + * Reposition the job by changing the modification time of + * the control file. + */ +static int +touch(q) + struct queue *q; +{ + struct timeval tvp[2]; + + tvp[0].tv_sec = tvp[1].tv_sec = --mtime; + tvp[0].tv_usec = tvp[1].tv_usec = 0; + return(utimes(q->q_name, tvp)); +} + +/* + * Checks if specified job name is in the printer's queue. + * Returns: negative (-1) if argument name is not in the queue. + */ +static int +doarg(job) + char *job; +{ + register struct queue **qq; + register int jobnum, n; + register char *cp, *machine; + int cnt = 0; + FILE *fp; + + /* + * Look for a job item consisting of system name, colon, number + * (example: ucbarpa:114) + */ + if ((cp = index(job, ':')) != NULL) { + machine = job; + *cp++ = '\0'; + job = cp; + } else + machine = NULL; + + /* + * Check for job specified by number (example: 112 or 235ucbarpa). + */ + if (isdigit(*job)) { + jobnum = 0; + do + jobnum = jobnum * 10 + (*job++ - '0'); + while (isdigit(*job)); + for (qq = queue + nitems; --qq >= queue; ) { + n = 0; + for (cp = (*qq)->q_name+3; isdigit(*cp); ) + n = n * 10 + (*cp++ - '0'); + if (jobnum != n) + continue; + if (*job && strcmp(job, cp) != 0) + continue; + if (machine != NULL && strcmp(machine, cp) != 0) + continue; + if (touch(*qq) == 0) { + printf("\tmoved %s\n", (*qq)->q_name); + cnt++; + } + } + return(cnt); + } + /* + * Process item consisting of owner's name (example: henry). + */ + for (qq = queue + nitems; --qq >= queue; ) { + if ((fp = fopen((*qq)->q_name, "r")) == NULL) + continue; + while (getline(fp) > 0) + if (line[0] == 'P') + break; + (void) fclose(fp); + if (line[0] != 'P' || strcmp(job, line+1) != 0) + continue; + if (touch(*qq) == 0) { + printf("\tmoved %s\n", (*qq)->q_name); + cnt++; + } + } + return(cnt); +} + +/* + * Enable everything and start printer (undo `down'). + */ +void +up(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: up {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + startpr(2); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + startpr(2); + } +} diff --git a/usr.sbin/lpr/lpc/cmdtab.c b/usr.sbin/lpr/lpc/cmdtab.c new file mode 100644 index 0000000..7619791 --- /dev/null +++ b/usr.sbin/lpr/lpc/cmdtab.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <sys/cdefs.h> + +#include "lpc.h" +#include "extern.h" + +/* + * lpc -- command tables + */ +char aborthelp[] = "terminate a spooling daemon immediately and disable printing"; +char cleanhelp[] = "remove cruft files from a queue"; +char enablehelp[] = "turn a spooling queue on"; +char disablehelp[] = "turn a spooling queue off"; +char downhelp[] = "do a 'stop' followed by 'disable' and put a message in status"; +char helphelp[] = "get help on commands"; +char quithelp[] = "exit lpc"; +char restarthelp[] = "kill (if possible) and restart a spooling daemon"; +char starthelp[] = "enable printing and start a spooling daemon"; +char statushelp[] = "show status of daemon and queue"; +char stophelp[] = "stop a spooling daemon after current job completes and disable printing"; +char topqhelp[] = "put job at top of printer queue"; +char uphelp[] = "enable everything and restart spooling daemon"; + +struct cmd cmdtab[] = { + { "abort", aborthelp, doabort, 1 }, + { "clean", cleanhelp, clean, 1 }, + { "enable", enablehelp, enable, 1 }, + { "exit", quithelp, quit, 0 }, + { "disable", disablehelp, disable, 1 }, + { "down", downhelp, down, 1 }, + { "help", helphelp, help, 0 }, + { "quit", quithelp, quit, 0 }, + { "restart", restarthelp, restart, 0 }, + { "start", starthelp, startcmd, 1 }, + { "status", statushelp, status, 0 }, + { "stop", stophelp, stop, 1 }, + { "topq", topqhelp, topq, 1 }, + { "up", uphelp, up, 1 }, + { "?", helphelp, help, 0 }, + { 0 }, +}; + +int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]); diff --git a/usr.sbin/lpr/lpc/extern.h b/usr.sbin/lpr/lpc/extern.h new file mode 100644 index 0000000..1b807b1 --- /dev/null +++ b/usr.sbin/lpr/lpc/extern.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/6/93 + */ + + +#include <sys/cdefs.h> + + +__BEGIN_DECLS +void clean __P((int, char **)); +void disable __P((int, char **)); +void doabort __P((int, char **)); +void down __P((int, char **)); +void enable __P((int, char **)); +void help __P((int, char **)); +void quit __P((int, char **)); +void restart __P((int, char **)); +void startcmd __P((int, char **)); +void status __P((int, char **)); +void stop __P((int, char **)); +void topq __P((int, char **)); +void up __P((int, char **)); +__END_DECLS + +extern int NCMDS; +extern struct cmd cmdtab[]; diff --git a/usr.sbin/lpr/lpc/lpc.8 b/usr.sbin/lpr/lpc/lpc.8 new file mode 100644 index 0000000..a786adc --- /dev/null +++ b/usr.sbin/lpr/lpc/lpc.8 @@ -0,0 +1,174 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lpc.8 8.3 (Berkeley) 4/19/94 +.\" +.Dd April 19, 1994 +.Dt LPC 8 +.Os BSD 4.2 +.Sh NAME +.Nm lpc +.Nd line printer control program +.Sh SYNOPSIS +.Nm lpc +.Oo +.Ar command +.Op Ar argument ... +.Oc +.Sh DESCRIPTION +.Nm Lpc +is used by the system administrator to control the +operation of the line printer system. +For each line printer configured in +.Pa /etc/printcap , +.Nm lpc +may be used to: +.Bl -bullet -offset indent +.It +disable or enable a printer, +.It +disable or enable a printer's spooling queue, +.It +rearrange the order of jobs in a spooling queue, +.It +find the status of printers, and their associated +spooling queues and printer daemons. +.El +.Pp +Without any arguments, +.Nm lpc +will prompt for commands from the standard input. +If arguments are supplied, +.Nm lpc +interprets the first argument as a command and the remaining +arguments as parameters to the command. The standard input +may be redirected causing +.Nm lpc +to read commands from file. +Commands may be abbreviated; +the following is the list of recognized commands. +.Pp +.Bl -tag -width Ds -compact +.It Ic \&? No [ command ... ] +.It Ic help No [ command ... ] +Print a short description of each command specified in the argument list, +or, if no argument is given, a list of the recognized commands. +.Pp +.It Ic abort No {\ all\ |\ printer\ } +Terminate an active spooling daemon on the local host immediately and +then disable printing (preventing new daemons from being started by +.Xr lpr ) +for the specified printers. +.Pp +.It Ic clean No {\ all\ |\ printer\ } +Remove any temporary files, data files, and control files that cannot +be printed (i.e., do not form a complete printer job) +from the specified printer queue(s) on the local machine. +.Pp +.It Ic disable No {\ all\ |\ printer\ } +Turn the specified printer queues off. This prevents new +printer jobs from being entered into the queue by +.Xr lpr . +.Pp +.It Ic down No {\ all\ |\ printer\ } message ... +Turn the specified printer queue off, disable printing and put +.Em message +in the printer status file. The message doesn't need to be quoted, the +remaining arguments are treated like +.Xr echo 1 . +This is normally used to take a printer down and let others know why +.Xr lpq 1 +will indicate the printer is down and print the status message). +.Pp +.It Ic enable No {\ all\ |\ printer\ } +Enable spooling on the local queue for the listed printers. +This will allow +.Xr lpr 1 +to put new jobs in the spool queue. +.Pp +.It Ic exit +.It Ic quit +Exit from lpc. +.Pp +.It Ic restart No {\ all\ |\ printer\ } +Attempt to start a new printer daemon. +This is useful when some abnormal condition causes the daemon to +die unexpectedly, leaving jobs in the queue. +.Xr Lpq +will report that there is no daemon present when this condition occurs. +If the user is the super-user, +try to abort the current daemon first (i.e., kill and restart a stuck daemon). +.Pp +.It Ic start No {\ all\ |\ printer\ } +Enable printing and start a spooling daemon for the listed printers. +.Pp +.It Ic status No {\ all\ |\ printer\ } +Display the status of daemons and queues on the local machine. +.Pp +.It Ic stop No {\ all\ |\ printer\ } +Stop a spooling daemon after the current job completes and disable +printing. +.Pp +.It Ic topq No printer\ [\ jobnum\ ...\ ]\ [\ user\ ...\ ] +Place the jobs in the order listed at the top of the printer queue. +.Pp +.It Ic up No {\ all\ |\ printer\ } +Enable everything and start a new printer daemon. Undoes the effects of +.Ic down . +.Sh FILES +.Bl -tag -width /var/spool/*/lockx -compact +.It Pa /etc/printcap +printer description file +.It Pa /var/spool/* +spool directories +.It Pa /var/spool/*/lock +lock file for queue control +.El +.Sh SEE ALSO +.Xr lpd 8 , +.Xr lpr 1 , +.Xr lpq 1 , +.Xr lprm 1 , +.Xr printcap 5 +.Sh DIAGNOSTICS +.Bl -tag -width Ds +.It Sy "?Ambiguous command" +abbreviation matches more than one command +.It Sy "?Invalid command" +no match was found +.It Sy "?Privileged command" +command can be executed by root only +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/usr.sbin/lpr/lpc/lpc.c b/usr.sbin/lpr/lpc/lpc.c new file mode 100644 index 0000000..01cfc12 --- /dev/null +++ b/usr.sbin/lpr/lpc/lpc.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lpc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <sys/param.h> + +#include <dirent.h> +#include <signal.h> +#include <setjmp.h> +#include <syslog.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include "lp.h" +#include "lpc.h" +#include "extern.h" + +/* + * lpc -- line printer control program + */ + +int fromatty; + +char cmdline[200]; +int margc; +char *margv[20]; +int top; + +jmp_buf toplevel; + +static void cmdscanner __P((int)); +static struct cmd *getcmd __P((char *)); +static void intr __P((int)); +static void makeargv __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register struct cmd *c; + + name = argv[0]; + openlog("lpd", 0, LOG_LPR); + + if (--argc > 0) { + c = getcmd(*++argv); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + exit(1); + } + if (c == 0) { + printf("?Invalid command\n"); + exit(1); + } + if (c->c_priv && getuid()) { + printf("?Privileged command\n"); + exit(1); + } + (*c->c_handler)(argc, argv); + exit(0); + } + fromatty = isatty(fileno(stdin)); + top = setjmp(toplevel) == 0; + if (top) + signal(SIGINT, intr); + for (;;) { + cmdscanner(top); + top = 1; + } +} + +static void +intr(signo) + int signo; +{ + if (!fromatty) + exit(0); + longjmp(toplevel, 1); +} + +/* + * Command parser. + */ +static void +cmdscanner(top) + int top; +{ + register struct cmd *c; + + if (!top) + putchar('\n'); + for (;;) { + if (fromatty) { + printf("lpc> "); + fflush(stdout); + } + if (fgets(cmdline, sizeof(cmdline), stdin) == 0) + quit(0, NULL); + if (cmdline[0] == 0 || cmdline[0] == '\n') + break; + makeargv(); + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + if (c->c_priv && getuid()) { + printf("?Privileged command\n"); + continue; + } + (*c->c_handler)(margc, margv); + } + longjmp(toplevel, 0); +} + +struct cmd * +getcmd(name) + register char *name; +{ + register char *p, *q; + register struct cmd *c, *found; + register int nmatches, longest; + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; p = c->c_name; c++) { + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return(c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return((struct cmd *)-1); + return(found); +} + +/* + * Slice a string up into argc/argv. + */ +static void +makeargv() +{ + register char *cp; + register char **argp = margv; + + margc = 0; + for (cp = cmdline; *cp;) { + while (isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *argp++ = cp; + margc += 1; + while (*cp != '\0' && !isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *cp++ = '\0'; + } + *argp++ = 0; +} + +#define HELPINDENT (sizeof ("directory")) + +/* + * Help command. + */ +void +help(argc, argv) + int argc; + char *argv[]; +{ + register struct cmd *c; + + if (argc == 1) { + register int i, j, w; + int columns, width = 0, lines; + extern int NCMDS; + + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c->c_name; c++) { + int len = strlen(c->c_name); + + if (len > width) + width = len; + } + width = (width + 8) &~ 7; + columns = 80 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + c = cmdtab + j * lines + i; + if (c->c_name) + printf("%s", c->c_name); + if (c + lines >= &cmdtab[NCMDS]) { + printf("\n"); + break; + } + w = strlen(c->c_name); + while (w < width) { + w = (w + 8) &~ 7; + putchar('\t'); + } + } + } + return; + } + while (--argc > 0) { + register char *arg; + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + printf("?Ambiguous help command %s\n", arg); + else if (c == (struct cmd *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%-*s\t%s\n", HELPINDENT, + c->c_name, c->c_help); + } +} diff --git a/usr.sbin/lpr/lpc/lpc.h b/usr.sbin/lpr/lpc/lpc.h new file mode 100644 index 0000000..5e71203 --- /dev/null +++ b/usr.sbin/lpr/lpc/lpc.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lpc.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Line printer control program. + */ +struct cmd { + char *c_name; /* command name */ + char *c_help; /* help message */ + /* routine to do the work */ + void (*c_handler) __P((int, char *[])); + int c_priv; /* privileged command */ +}; |