122428Sdist /* 222428Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*56121Selan * Redistribution and use in source and binary forms, with or without 6*56121Selan * modification, are permitted provided that the following conditions 7*56121Selan * are met: 8*56121Selan * 1. Redistributions of source code must retain the above copyright 9*56121Selan * notice, this list of conditions and the following disclaimer. 10*56121Selan * 2. Redistributions in binary form must reproduce the above copyright 11*56121Selan * notice, this list of conditions and the following disclaimer in the 12*56121Selan * documentation and/or other materials provided with the distribution. 13*56121Selan * 3. All advertising materials mentioning features or use of this software 14*56121Selan * must display the following acknowledgement: 15*56121Selan * This product includes software developed by the University of 16*56121Selan * California, Berkeley and its contributors. 17*56121Selan * 4. Neither the name of the University nor the names of its contributors 18*56121Selan * may be used to endorse or promote products derived from this software 19*56121Selan * without specific prior written permission. 20*56121Selan * 21*56121Selan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22*56121Selan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*56121Selan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*56121Selan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25*56121Selan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*56121Selan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*56121Selan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*56121Selan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*56121Selan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*56121Selan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*56121Selan * SUCH DAMAGE. 3222428Sdist */ 3322428Sdist 3412380Sralph #ifndef lint 3522428Sdist char copyright[] = 3622428Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 3722428Sdist All rights reserved.\n"; 3834203Sbostic #endif /* not lint */ 3912380Sralph 4022428Sdist #ifndef lint 41*56121Selan static char sccsid[] = "@(#)lpc.c 5.13 (Berkeley) 8/6/92"; 4234203Sbostic #endif /* not lint */ 4322428Sdist 4455472Sbostic #include <sys/param.h> 4555472Sbostic 4655472Sbostic #include <dirent.h> 4712380Sralph #include <signal.h> 4812380Sralph #include <setjmp.h> 4925494Seric #include <syslog.h> 5055472Sbostic #include <unistd.h> 5155472Sbostic #include <stdlib.h> 5255472Sbostic #include <stdio.h> 5355472Sbostic #include <ctype.h> 5455472Sbostic #include <string.h> 5555472Sbostic #include "lp.h" 5612380Sralph #include "lpc.h" 5755472Sbostic #include "extern.h" 5812380Sralph 5955472Sbostic /* 6055472Sbostic * lpc -- line printer control program 6155472Sbostic */ 6255472Sbostic 6312380Sralph int fromatty; 6412380Sralph 6512380Sralph char cmdline[200]; 6612380Sralph int margc; 6712380Sralph char *margv[20]; 6812380Sralph int top; 6912380Sralph 7012380Sralph jmp_buf toplevel; 7112380Sralph 7255472Sbostic static void cmdscanner __P((int)); 7355472Sbostic static struct cmd *getcmd __P((char *)); 7455472Sbostic static void intr __P((int)); 7555472Sbostic static void makeargv __P((void)); 7655472Sbostic 7755472Sbostic int 7812380Sralph main(argc, argv) 7955472Sbostic int argc; 8012380Sralph char *argv[]; 8112380Sralph { 8212380Sralph register struct cmd *c; 8312380Sralph 8412744Sralph name = argv[0]; 8525494Seric openlog("lpd", 0, LOG_LPR); 8612744Sralph 8712380Sralph if (--argc > 0) { 8812380Sralph c = getcmd(*++argv); 8912380Sralph if (c == (struct cmd *)-1) { 9012380Sralph printf("?Ambiguous command\n"); 9112380Sralph exit(1); 9212380Sralph } 9312380Sralph if (c == 0) { 9412380Sralph printf("?Invalid command\n"); 9512380Sralph exit(1); 9612380Sralph } 9712380Sralph if (c->c_priv && getuid()) { 9812380Sralph printf("?Privileged command\n"); 9912380Sralph exit(1); 10012380Sralph } 10112380Sralph (*c->c_handler)(argc, argv); 10212380Sralph exit(0); 10312380Sralph } 10412380Sralph fromatty = isatty(fileno(stdin)); 10512380Sralph top = setjmp(toplevel) == 0; 10612380Sralph if (top) 10713147Ssam signal(SIGINT, intr); 10812380Sralph for (;;) { 10912380Sralph cmdscanner(top); 11012380Sralph top = 1; 11112380Sralph } 11212380Sralph } 11312380Sralph 11455472Sbostic static void 11555472Sbostic intr(signo) 11655472Sbostic int signo; 11712380Sralph { 11812380Sralph if (!fromatty) 11912380Sralph exit(0); 12012380Sralph longjmp(toplevel, 1); 12112380Sralph } 12212380Sralph 12312380Sralph /* 12412380Sralph * Command parser. 12512380Sralph */ 12655472Sbostic static void 12712380Sralph cmdscanner(top) 12812380Sralph int top; 12912380Sralph { 13012380Sralph register struct cmd *c; 13112380Sralph 13212380Sralph if (!top) 13312380Sralph putchar('\n'); 13412380Sralph for (;;) { 13512380Sralph if (fromatty) { 13612380Sralph printf("lpc> "); 13712380Sralph fflush(stdout); 13812380Sralph } 13936247Sbostic if (fgets(cmdline, sizeof(cmdline), stdin) == 0) 14055472Sbostic quit(0, NULL); 14140549Stef if (cmdline[0] == 0 || cmdline[0] == '\n') 14212380Sralph break; 14312380Sralph makeargv(); 14412380Sralph c = getcmd(margv[0]); 14512380Sralph if (c == (struct cmd *)-1) { 14612380Sralph printf("?Ambiguous command\n"); 14712380Sralph continue; 14812380Sralph } 14912380Sralph if (c == 0) { 15012380Sralph printf("?Invalid command\n"); 15112380Sralph continue; 15212380Sralph } 15312380Sralph if (c->c_priv && getuid()) { 15412380Sralph printf("?Privileged command\n"); 15512380Sralph continue; 15612380Sralph } 15712380Sralph (*c->c_handler)(margc, margv); 15812380Sralph } 15912380Sralph longjmp(toplevel, 0); 16012380Sralph } 16112380Sralph 16212380Sralph struct cmd * 16312380Sralph getcmd(name) 16412380Sralph register char *name; 16512380Sralph { 16612380Sralph register char *p, *q; 16712380Sralph register struct cmd *c, *found; 16812380Sralph register int nmatches, longest; 16912380Sralph 17012380Sralph longest = 0; 17112380Sralph nmatches = 0; 17212380Sralph found = 0; 17312380Sralph for (c = cmdtab; p = c->c_name; c++) { 17412380Sralph for (q = name; *q == *p++; q++) 17512380Sralph if (*q == 0) /* exact match? */ 17612380Sralph return(c); 17712380Sralph if (!*q) { /* the name was a prefix */ 17812380Sralph if (q - name > longest) { 17912380Sralph longest = q - name; 18012380Sralph nmatches = 1; 18112380Sralph found = c; 18212380Sralph } else if (q - name == longest) 18312380Sralph nmatches++; 18412380Sralph } 18512380Sralph } 18612380Sralph if (nmatches > 1) 18712380Sralph return((struct cmd *)-1); 18812380Sralph return(found); 18912380Sralph } 19012380Sralph 19112380Sralph /* 19212380Sralph * Slice a string up into argc/argv. 19312380Sralph */ 19455472Sbostic static void 19512380Sralph makeargv() 19612380Sralph { 19712380Sralph register char *cp; 19812380Sralph register char **argp = margv; 19912380Sralph 20012380Sralph margc = 0; 20112380Sralph for (cp = cmdline; *cp;) { 20212380Sralph while (isspace(*cp)) 20312380Sralph cp++; 20412380Sralph if (*cp == '\0') 20512380Sralph break; 20612380Sralph *argp++ = cp; 20712380Sralph margc += 1; 20812380Sralph while (*cp != '\0' && !isspace(*cp)) 20912380Sralph cp++; 21012380Sralph if (*cp == '\0') 21112380Sralph break; 21212380Sralph *cp++ = '\0'; 21312380Sralph } 21412380Sralph *argp++ = 0; 21512380Sralph } 21612380Sralph 21712380Sralph #define HELPINDENT (sizeof ("directory")) 21812380Sralph 21912380Sralph /* 22012380Sralph * Help command. 22112380Sralph */ 22255472Sbostic void 22312380Sralph help(argc, argv) 22412380Sralph int argc; 22512380Sralph char *argv[]; 22612380Sralph { 22712380Sralph register struct cmd *c; 22812380Sralph 22912380Sralph if (argc == 1) { 23012380Sralph register int i, j, w; 23112380Sralph int columns, width = 0, lines; 23212380Sralph extern int NCMDS; 23312380Sralph 23412380Sralph printf("Commands may be abbreviated. Commands are:\n\n"); 23539727Sbostic for (c = cmdtab; c->c_name; c++) { 23612380Sralph int len = strlen(c->c_name); 23712380Sralph 23812380Sralph if (len > width) 23912380Sralph width = len; 24012380Sralph } 24112380Sralph width = (width + 8) &~ 7; 24212380Sralph columns = 80 / width; 24312380Sralph if (columns == 0) 24412380Sralph columns = 1; 24512380Sralph lines = (NCMDS + columns - 1) / columns; 24612380Sralph for (i = 0; i < lines; i++) { 24712380Sralph for (j = 0; j < columns; j++) { 24812380Sralph c = cmdtab + j * lines + i; 24939727Sbostic if (c->c_name) 25039727Sbostic printf("%s", c->c_name); 25112380Sralph if (c + lines >= &cmdtab[NCMDS]) { 25212380Sralph printf("\n"); 25312380Sralph break; 25412380Sralph } 25512380Sralph w = strlen(c->c_name); 25612380Sralph while (w < width) { 25712380Sralph w = (w + 8) &~ 7; 25812380Sralph putchar('\t'); 25912380Sralph } 26012380Sralph } 26112380Sralph } 26212380Sralph return; 26312380Sralph } 26412380Sralph while (--argc > 0) { 26512380Sralph register char *arg; 26612380Sralph arg = *++argv; 26712380Sralph c = getcmd(arg); 26812380Sralph if (c == (struct cmd *)-1) 26912380Sralph printf("?Ambiguous help command %s\n", arg); 27012380Sralph else if (c == (struct cmd *)0) 27112380Sralph printf("?Invalid help command %s\n", arg); 27212380Sralph else 27312380Sralph printf("%-*s\t%s\n", HELPINDENT, 27412380Sralph c->c_name, c->c_help); 27512380Sralph } 27612380Sralph } 277