10b561052SJoerg Wunsch /* 20b561052SJoerg Wunsch * Copyright (c) 1983, 1993, 1994 30b561052SJoerg Wunsch * The Regents of the University of California. All rights reserved. 40b561052SJoerg Wunsch * 50b561052SJoerg Wunsch * 60b561052SJoerg Wunsch * Redistribution and use in source and binary forms, with or without 70b561052SJoerg Wunsch * modification, are permitted provided that the following conditions 80b561052SJoerg Wunsch * are met: 90b561052SJoerg Wunsch * 1. Redistributions of source code must retain the above copyright 100b561052SJoerg Wunsch * notice, this list of conditions and the following disclaimer. 110b561052SJoerg Wunsch * 2. Redistributions in binary form must reproduce the above copyright 120b561052SJoerg Wunsch * notice, this list of conditions and the following disclaimer in the 130b561052SJoerg Wunsch * documentation and/or other materials provided with the distribution. 140b561052SJoerg Wunsch * 3. All advertising materials mentioning features or use of this software 150b561052SJoerg Wunsch * must display the following acknowledgement: 160b561052SJoerg Wunsch * This product includes software developed by the University of 170b561052SJoerg Wunsch * California, Berkeley and its contributors. 180b561052SJoerg Wunsch * 4. Neither the name of the University nor the names of its contributors 190b561052SJoerg Wunsch * may be used to endorse or promote products derived from this software 200b561052SJoerg Wunsch * without specific prior written permission. 210b561052SJoerg Wunsch * 220b561052SJoerg Wunsch * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 230b561052SJoerg Wunsch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 240b561052SJoerg Wunsch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 250b561052SJoerg Wunsch * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 260b561052SJoerg Wunsch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 270b561052SJoerg Wunsch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 280b561052SJoerg Wunsch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 290b561052SJoerg Wunsch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 300b561052SJoerg Wunsch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 310b561052SJoerg Wunsch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 320b561052SJoerg Wunsch * SUCH DAMAGE. 330b561052SJoerg Wunsch */ 340b561052SJoerg Wunsch 350b561052SJoerg Wunsch #ifndef lint 360b561052SJoerg Wunsch static char copyright[] = 370b561052SJoerg Wunsch "@(#) Copyright (c) 1983, 1993, 1994\n\ 380b561052SJoerg Wunsch The Regents of the University of California. All rights reserved.\n"; 390b561052SJoerg Wunsch #endif /* not lint */ 400b561052SJoerg Wunsch 410b561052SJoerg Wunsch #ifndef lint 420b561052SJoerg Wunsch static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95"; 430b561052SJoerg Wunsch #endif /* not lint */ 440b561052SJoerg Wunsch 450b561052SJoerg Wunsch /* 460b561052SJoerg Wunsch * lpd -- line printer daemon. 470b561052SJoerg Wunsch * 480b561052SJoerg Wunsch * Listen for a connection and perform the requested operation. 490b561052SJoerg Wunsch * Operations are: 500b561052SJoerg Wunsch * \1printer\n 510b561052SJoerg Wunsch * check the queue for jobs and print any found. 520b561052SJoerg Wunsch * \2printer\n 530b561052SJoerg Wunsch * receive a job from another machine and queue it. 540b561052SJoerg Wunsch * \3printer [users ...] [jobs ...]\n 550b561052SJoerg Wunsch * return the current state of the queue (short form). 560b561052SJoerg Wunsch * \4printer [users ...] [jobs ...]\n 570b561052SJoerg Wunsch * return the current state of the queue (long form). 580b561052SJoerg Wunsch * \5printer person [users ...] [jobs ...]\n 590b561052SJoerg Wunsch * remove jobs from the queue. 600b561052SJoerg Wunsch * 610b561052SJoerg Wunsch * Strategy to maintain protected spooling area: 620b561052SJoerg Wunsch * 1. Spooling area is writable only by daemon and spooling group 630b561052SJoerg Wunsch * 2. lpr runs setuid root and setgrp spooling group; it uses 640b561052SJoerg Wunsch * root to access any file it wants (verifying things before 650b561052SJoerg Wunsch * with an access call) and group id to know how it should 660b561052SJoerg Wunsch * set up ownership of files in the spooling area. 670b561052SJoerg Wunsch * 3. Files in spooling area are owned by root, group spooling 680b561052SJoerg Wunsch * group, with mode 660. 690b561052SJoerg Wunsch * 4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to 700b561052SJoerg Wunsch * access files and printer. Users can't get to anything 710b561052SJoerg Wunsch * w/o help of lpq and lprm programs. 720b561052SJoerg Wunsch */ 730b561052SJoerg Wunsch 740b561052SJoerg Wunsch #include <sys/param.h> 750b561052SJoerg Wunsch #include <sys/wait.h> 760b561052SJoerg Wunsch #include <sys/types.h> 770b561052SJoerg Wunsch #include <sys/socket.h> 780b561052SJoerg Wunsch #include <sys/un.h> 790b561052SJoerg Wunsch #include <sys/stat.h> 800b561052SJoerg Wunsch #include <sys/file.h> 810b561052SJoerg Wunsch #include <netinet/in.h> 820b561052SJoerg Wunsch 830b561052SJoerg Wunsch #include <netdb.h> 840b561052SJoerg Wunsch #include <unistd.h> 850b561052SJoerg Wunsch #include <syslog.h> 860b561052SJoerg Wunsch #include <signal.h> 870b561052SJoerg Wunsch #include <errno.h> 880b561052SJoerg Wunsch #include <fcntl.h> 890b561052SJoerg Wunsch #include <dirent.h> 900b561052SJoerg Wunsch #include <stdio.h> 910b561052SJoerg Wunsch #include <stdlib.h> 920b561052SJoerg Wunsch #include <string.h> 930b561052SJoerg Wunsch #include <ctype.h> 940b561052SJoerg Wunsch #include "lp.h" 950b561052SJoerg Wunsch #include "lp.local.h" 960b561052SJoerg Wunsch #include "pathnames.h" 970b561052SJoerg Wunsch #include "extern.h" 980b561052SJoerg Wunsch 990b561052SJoerg Wunsch int lflag; /* log requests flag */ 1000b561052SJoerg Wunsch int from_remote; /* from remote socket */ 1010b561052SJoerg Wunsch 1020b561052SJoerg Wunsch static void reapchild __P((int)); 1030b561052SJoerg Wunsch static void mcleanup __P((int)); 1040b561052SJoerg Wunsch static void doit __P((void)); 1050b561052SJoerg Wunsch static void startup __P((void)); 1060b561052SJoerg Wunsch static void chkhost __P((struct sockaddr_in *)); 1070b561052SJoerg Wunsch static int ckqueue __P((char *)); 1080b561052SJoerg Wunsch 1090b561052SJoerg Wunsch int 1100b561052SJoerg Wunsch main(argc, argv) 1110b561052SJoerg Wunsch int argc; 1120b561052SJoerg Wunsch char **argv; 1130b561052SJoerg Wunsch { 1140b561052SJoerg Wunsch int f, funix, finet, options, fromlen; 1150b561052SJoerg Wunsch fd_set defreadfds; 1160b561052SJoerg Wunsch struct sockaddr_un un, fromunix; 1170b561052SJoerg Wunsch struct sockaddr_in sin, frominet; 1180b561052SJoerg Wunsch int omask, lfd; 1190b561052SJoerg Wunsch 1200b561052SJoerg Wunsch options = 0; 1210b561052SJoerg Wunsch gethostname(host, sizeof(host)); 1220b561052SJoerg Wunsch name = argv[0]; 1230b561052SJoerg Wunsch 1240b561052SJoerg Wunsch while (--argc > 0) { 1250b561052SJoerg Wunsch argv++; 1260b561052SJoerg Wunsch if (argv[0][0] == '-') 1270b561052SJoerg Wunsch switch (argv[0][1]) { 1280b561052SJoerg Wunsch case 'd': 1290b561052SJoerg Wunsch options |= SO_DEBUG; 1300b561052SJoerg Wunsch break; 1310b561052SJoerg Wunsch case 'l': 1320b561052SJoerg Wunsch lflag++; 1330b561052SJoerg Wunsch break; 1340b561052SJoerg Wunsch } 1350b561052SJoerg Wunsch } 1360b561052SJoerg Wunsch 1370b561052SJoerg Wunsch #ifndef DEBUG 1380b561052SJoerg Wunsch /* 1390b561052SJoerg Wunsch * Set up standard environment by detaching from the parent. 1400b561052SJoerg Wunsch */ 1410b561052SJoerg Wunsch daemon(0, 0); 1420b561052SJoerg Wunsch #endif 1430b561052SJoerg Wunsch 1440b561052SJoerg Wunsch openlog("lpd", LOG_PID, LOG_LPR); 1450b561052SJoerg Wunsch syslog(LOG_INFO, "restarted"); 1460b561052SJoerg Wunsch (void) umask(0); 1470b561052SJoerg Wunsch lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644); 1480b561052SJoerg Wunsch if (lfd < 0) { 1490b561052SJoerg Wunsch syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 1500b561052SJoerg Wunsch exit(1); 1510b561052SJoerg Wunsch } 1520b561052SJoerg Wunsch if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { 1530b561052SJoerg Wunsch if (errno == EWOULDBLOCK) /* active deamon present */ 1540b561052SJoerg Wunsch exit(0); 1550b561052SJoerg Wunsch syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 1560b561052SJoerg Wunsch exit(1); 1570b561052SJoerg Wunsch } 1580b561052SJoerg Wunsch ftruncate(lfd, 0); 1590b561052SJoerg Wunsch /* 1600b561052SJoerg Wunsch * write process id for others to know 1610b561052SJoerg Wunsch */ 1620b561052SJoerg Wunsch sprintf(line, "%u\n", getpid()); 1630b561052SJoerg Wunsch f = strlen(line); 1640b561052SJoerg Wunsch if (write(lfd, line, f) != f) { 1650b561052SJoerg Wunsch syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 1660b561052SJoerg Wunsch exit(1); 1670b561052SJoerg Wunsch } 1680b561052SJoerg Wunsch signal(SIGCHLD, reapchild); 1690b561052SJoerg Wunsch /* 1700b561052SJoerg Wunsch * Restart all the printers. 1710b561052SJoerg Wunsch */ 1720b561052SJoerg Wunsch startup(); 1730b561052SJoerg Wunsch (void) unlink(_PATH_SOCKETNAME); 1740b561052SJoerg Wunsch funix = socket(AF_UNIX, SOCK_STREAM, 0); 1750b561052SJoerg Wunsch if (funix < 0) { 1760b561052SJoerg Wunsch syslog(LOG_ERR, "socket: %m"); 1770b561052SJoerg Wunsch exit(1); 1780b561052SJoerg Wunsch } 1790b561052SJoerg Wunsch #define mask(s) (1 << ((s) - 1)) 1800b561052SJoerg Wunsch omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM)); 1810b561052SJoerg Wunsch signal(SIGHUP, mcleanup); 1820b561052SJoerg Wunsch signal(SIGINT, mcleanup); 1830b561052SJoerg Wunsch signal(SIGQUIT, mcleanup); 1840b561052SJoerg Wunsch signal(SIGTERM, mcleanup); 1850b561052SJoerg Wunsch memset(&un, 0, sizeof(un)); 1860b561052SJoerg Wunsch un.sun_family = AF_UNIX; 1870b561052SJoerg Wunsch strcpy(un.sun_path, _PATH_SOCKETNAME); 1880b561052SJoerg Wunsch #ifndef SUN_LEN 1890b561052SJoerg Wunsch #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) 1900b561052SJoerg Wunsch #endif 1910b561052SJoerg Wunsch if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) { 1920b561052SJoerg Wunsch syslog(LOG_ERR, "ubind: %m"); 1930b561052SJoerg Wunsch exit(1); 1940b561052SJoerg Wunsch } 1950b561052SJoerg Wunsch sigsetmask(omask); 1960b561052SJoerg Wunsch FD_ZERO(&defreadfds); 1970b561052SJoerg Wunsch FD_SET(funix, &defreadfds); 1980b561052SJoerg Wunsch listen(funix, 5); 1990b561052SJoerg Wunsch finet = socket(AF_INET, SOCK_STREAM, 0); 2000b561052SJoerg Wunsch if (finet >= 0) { 2010b561052SJoerg Wunsch struct servent *sp; 2020b561052SJoerg Wunsch 2030b561052SJoerg Wunsch if (options & SO_DEBUG) 2040b561052SJoerg Wunsch if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) { 2050b561052SJoerg Wunsch syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 2060b561052SJoerg Wunsch mcleanup(0); 2070b561052SJoerg Wunsch } 2080b561052SJoerg Wunsch sp = getservbyname("printer", "tcp"); 2090b561052SJoerg Wunsch if (sp == NULL) { 2100b561052SJoerg Wunsch syslog(LOG_ERR, "printer/tcp: unknown service"); 2110b561052SJoerg Wunsch mcleanup(0); 2120b561052SJoerg Wunsch } 2130b561052SJoerg Wunsch memset(&sin, 0, sizeof(sin)); 2140b561052SJoerg Wunsch sin.sin_family = AF_INET; 2150b561052SJoerg Wunsch sin.sin_port = sp->s_port; 2160b561052SJoerg Wunsch if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 2170b561052SJoerg Wunsch syslog(LOG_ERR, "bind: %m"); 2180b561052SJoerg Wunsch mcleanup(0); 2190b561052SJoerg Wunsch } 2200b561052SJoerg Wunsch FD_SET(finet, &defreadfds); 2210b561052SJoerg Wunsch listen(finet, 5); 2220b561052SJoerg Wunsch } 2230b561052SJoerg Wunsch /* 2240b561052SJoerg Wunsch * Main loop: accept, do a request, continue. 2250b561052SJoerg Wunsch */ 2260b561052SJoerg Wunsch memset(&frominet, 0, sizeof(frominet)); 2270b561052SJoerg Wunsch memset(&fromunix, 0, sizeof(fromunix)); 2280b561052SJoerg Wunsch for (;;) { 2290b561052SJoerg Wunsch int domain, nfds, s; 2300b561052SJoerg Wunsch fd_set readfds; 2310b561052SJoerg Wunsch 2320b561052SJoerg Wunsch FD_COPY(&defreadfds, &readfds); 2330b561052SJoerg Wunsch nfds = select(20, &readfds, 0, 0, 0); 2340b561052SJoerg Wunsch if (nfds <= 0) { 2350b561052SJoerg Wunsch if (nfds < 0 && errno != EINTR) 2360b561052SJoerg Wunsch syslog(LOG_WARNING, "select: %m"); 2370b561052SJoerg Wunsch continue; 2380b561052SJoerg Wunsch } 2390b561052SJoerg Wunsch if (FD_ISSET(funix, &readfds)) { 2400b561052SJoerg Wunsch domain = AF_UNIX, fromlen = sizeof(fromunix); 2410b561052SJoerg Wunsch s = accept(funix, 2420b561052SJoerg Wunsch (struct sockaddr *)&fromunix, &fromlen); 2430b561052SJoerg Wunsch } else /* if (FD_ISSET(finet, &readfds)) */ { 2440b561052SJoerg Wunsch domain = AF_INET, fromlen = sizeof(frominet); 2450b561052SJoerg Wunsch s = accept(finet, 2460b561052SJoerg Wunsch (struct sockaddr *)&frominet, &fromlen); 2470b561052SJoerg Wunsch } 2480b561052SJoerg Wunsch if (s < 0) { 2490b561052SJoerg Wunsch if (errno != EINTR) 2500b561052SJoerg Wunsch syslog(LOG_WARNING, "accept: %m"); 2510b561052SJoerg Wunsch continue; 2520b561052SJoerg Wunsch } 2530b561052SJoerg Wunsch if (fork() == 0) { 2540b561052SJoerg Wunsch signal(SIGCHLD, SIG_IGN); 2550b561052SJoerg Wunsch signal(SIGHUP, SIG_IGN); 2560b561052SJoerg Wunsch signal(SIGINT, SIG_IGN); 2570b561052SJoerg Wunsch signal(SIGQUIT, SIG_IGN); 2580b561052SJoerg Wunsch signal(SIGTERM, SIG_IGN); 2590b561052SJoerg Wunsch (void) close(funix); 2600b561052SJoerg Wunsch (void) close(finet); 2610b561052SJoerg Wunsch dup2(s, 1); 2620b561052SJoerg Wunsch (void) close(s); 2630b561052SJoerg Wunsch if (domain == AF_INET) { 2640b561052SJoerg Wunsch from_remote = 1; 2650b561052SJoerg Wunsch chkhost(&frominet); 2660b561052SJoerg Wunsch } else 2670b561052SJoerg Wunsch from_remote = 0; 2680b561052SJoerg Wunsch doit(); 2690b561052SJoerg Wunsch exit(0); 2700b561052SJoerg Wunsch } 2710b561052SJoerg Wunsch (void) close(s); 2720b561052SJoerg Wunsch } 2730b561052SJoerg Wunsch } 2740b561052SJoerg Wunsch 2750b561052SJoerg Wunsch static void 2760b561052SJoerg Wunsch reapchild(signo) 2770b561052SJoerg Wunsch int signo; 2780b561052SJoerg Wunsch { 2790b561052SJoerg Wunsch union wait status; 2800b561052SJoerg Wunsch 2810b561052SJoerg Wunsch while (wait3((int *)&status, WNOHANG, 0) > 0) 2820b561052SJoerg Wunsch ; 2830b561052SJoerg Wunsch } 2840b561052SJoerg Wunsch 2850b561052SJoerg Wunsch static void 2860b561052SJoerg Wunsch mcleanup(signo) 2870b561052SJoerg Wunsch int signo; 2880b561052SJoerg Wunsch { 2890b561052SJoerg Wunsch if (lflag) 2900b561052SJoerg Wunsch syslog(LOG_INFO, "exiting"); 2910b561052SJoerg Wunsch unlink(_PATH_SOCKETNAME); 2920b561052SJoerg Wunsch exit(0); 2930b561052SJoerg Wunsch } 2940b561052SJoerg Wunsch 2950b561052SJoerg Wunsch /* 2960b561052SJoerg Wunsch * Stuff for handling job specifications 2970b561052SJoerg Wunsch */ 2980b561052SJoerg Wunsch char *user[MAXUSERS]; /* users to process */ 2990b561052SJoerg Wunsch int users; /* # of users in user array */ 3000b561052SJoerg Wunsch int requ[MAXREQUESTS]; /* job number of spool entries */ 3010b561052SJoerg Wunsch int requests; /* # of spool requests */ 3020b561052SJoerg Wunsch char *person; /* name of person doing lprm */ 3030b561052SJoerg Wunsch 3040b561052SJoerg Wunsch char fromb[MAXHOSTNAMELEN]; /* buffer for client's machine name */ 3050b561052SJoerg Wunsch char cbuf[BUFSIZ]; /* command line buffer */ 3060b561052SJoerg Wunsch char *cmdnames[] = { 3070b561052SJoerg Wunsch "null", 3080b561052SJoerg Wunsch "printjob", 3090b561052SJoerg Wunsch "recvjob", 3100b561052SJoerg Wunsch "displayq short", 3110b561052SJoerg Wunsch "displayq long", 3120b561052SJoerg Wunsch "rmjob" 3130b561052SJoerg Wunsch }; 3140b561052SJoerg Wunsch 3150b561052SJoerg Wunsch static void 3160b561052SJoerg Wunsch doit() 3170b561052SJoerg Wunsch { 3180b561052SJoerg Wunsch register char *cp; 3190b561052SJoerg Wunsch register int n; 3200b561052SJoerg Wunsch 3210b561052SJoerg Wunsch for (;;) { 3220b561052SJoerg Wunsch cp = cbuf; 3230b561052SJoerg Wunsch do { 3240b561052SJoerg Wunsch if (cp >= &cbuf[sizeof(cbuf) - 1]) 3250b561052SJoerg Wunsch fatal("Command line too long"); 3260b561052SJoerg Wunsch if ((n = read(1, cp, 1)) != 1) { 3270b561052SJoerg Wunsch if (n < 0) 3280b561052SJoerg Wunsch fatal("Lost connection"); 3290b561052SJoerg Wunsch return; 3300b561052SJoerg Wunsch } 3310b561052SJoerg Wunsch } while (*cp++ != '\n'); 3320b561052SJoerg Wunsch *--cp = '\0'; 3330b561052SJoerg Wunsch cp = cbuf; 3340b561052SJoerg Wunsch if (lflag) { 3350b561052SJoerg Wunsch if (*cp >= '\1' && *cp <= '\5') 3360b561052SJoerg Wunsch syslog(LOG_INFO, "%s requests %s %s", 3370b561052SJoerg Wunsch from, cmdnames[*cp], cp+1); 3380b561052SJoerg Wunsch else 3390b561052SJoerg Wunsch syslog(LOG_INFO, "bad request (%d) from %s", 3400b561052SJoerg Wunsch *cp, from); 3410b561052SJoerg Wunsch } 3420b561052SJoerg Wunsch switch (*cp++) { 3430b561052SJoerg Wunsch case '\1': /* check the queue and print any jobs there */ 3440b561052SJoerg Wunsch printer = cp; 3450b561052SJoerg Wunsch printjob(); 3460b561052SJoerg Wunsch break; 3470b561052SJoerg Wunsch case '\2': /* receive files to be queued */ 3480b561052SJoerg Wunsch if (!from_remote) { 3490b561052SJoerg Wunsch syslog(LOG_INFO, "illegal request (%d)", *cp); 3500b561052SJoerg Wunsch exit(1); 3510b561052SJoerg Wunsch } 3520b561052SJoerg Wunsch printer = cp; 3530b561052SJoerg Wunsch recvjob(); 3540b561052SJoerg Wunsch break; 3550b561052SJoerg Wunsch case '\3': /* display the queue (short form) */ 3560b561052SJoerg Wunsch case '\4': /* display the queue (long form) */ 3570b561052SJoerg Wunsch printer = cp; 3580b561052SJoerg Wunsch while (*cp) { 3590b561052SJoerg Wunsch if (*cp != ' ') { 3600b561052SJoerg Wunsch cp++; 3610b561052SJoerg Wunsch continue; 3620b561052SJoerg Wunsch } 3630b561052SJoerg Wunsch *cp++ = '\0'; 3640b561052SJoerg Wunsch while (isspace(*cp)) 3650b561052SJoerg Wunsch cp++; 3660b561052SJoerg Wunsch if (*cp == '\0') 3670b561052SJoerg Wunsch break; 3680b561052SJoerg Wunsch if (isdigit(*cp)) { 3690b561052SJoerg Wunsch if (requests >= MAXREQUESTS) 3700b561052SJoerg Wunsch fatal("Too many requests"); 3710b561052SJoerg Wunsch requ[requests++] = atoi(cp); 3720b561052SJoerg Wunsch } else { 3730b561052SJoerg Wunsch if (users >= MAXUSERS) 3740b561052SJoerg Wunsch fatal("Too many users"); 3750b561052SJoerg Wunsch user[users++] = cp; 3760b561052SJoerg Wunsch } 3770b561052SJoerg Wunsch } 3780b561052SJoerg Wunsch displayq(cbuf[0] - '\3'); 3790b561052SJoerg Wunsch exit(0); 3800b561052SJoerg Wunsch case '\5': /* remove a job from the queue */ 3810b561052SJoerg Wunsch if (!from_remote) { 3820b561052SJoerg Wunsch syslog(LOG_INFO, "illegal request (%d)", *cp); 3830b561052SJoerg Wunsch exit(1); 3840b561052SJoerg Wunsch } 3850b561052SJoerg Wunsch printer = cp; 3860b561052SJoerg Wunsch while (*cp && *cp != ' ') 3870b561052SJoerg Wunsch cp++; 3880b561052SJoerg Wunsch if (!*cp) 3890b561052SJoerg Wunsch break; 3900b561052SJoerg Wunsch *cp++ = '\0'; 3910b561052SJoerg Wunsch person = cp; 3920b561052SJoerg Wunsch while (*cp) { 3930b561052SJoerg Wunsch if (*cp != ' ') { 3940b561052SJoerg Wunsch cp++; 3950b561052SJoerg Wunsch continue; 3960b561052SJoerg Wunsch } 3970b561052SJoerg Wunsch *cp++ = '\0'; 3980b561052SJoerg Wunsch while (isspace(*cp)) 3990b561052SJoerg Wunsch cp++; 4000b561052SJoerg Wunsch if (*cp == '\0') 4010b561052SJoerg Wunsch break; 4020b561052SJoerg Wunsch if (isdigit(*cp)) { 4030b561052SJoerg Wunsch if (requests >= MAXREQUESTS) 4040b561052SJoerg Wunsch fatal("Too many requests"); 4050b561052SJoerg Wunsch requ[requests++] = atoi(cp); 4060b561052SJoerg Wunsch } else { 4070b561052SJoerg Wunsch if (users >= MAXUSERS) 4080b561052SJoerg Wunsch fatal("Too many users"); 4090b561052SJoerg Wunsch user[users++] = cp; 4100b561052SJoerg Wunsch } 4110b561052SJoerg Wunsch } 4120b561052SJoerg Wunsch rmjob(); 4130b561052SJoerg Wunsch break; 4140b561052SJoerg Wunsch } 4150b561052SJoerg Wunsch fatal("Illegal service request"); 4160b561052SJoerg Wunsch } 4170b561052SJoerg Wunsch } 4180b561052SJoerg Wunsch 4190b561052SJoerg Wunsch /* 4200b561052SJoerg Wunsch * Make a pass through the printcap database and start printing any 4210b561052SJoerg Wunsch * files left from the last time the machine went down. 4220b561052SJoerg Wunsch */ 4230b561052SJoerg Wunsch static void 4240b561052SJoerg Wunsch startup() 4250b561052SJoerg Wunsch { 4260b561052SJoerg Wunsch char *buf; 4270b561052SJoerg Wunsch register char *cp; 4280b561052SJoerg Wunsch int pid; 4290b561052SJoerg Wunsch 4300b561052SJoerg Wunsch /* 4310b561052SJoerg Wunsch * Restart the daemons. 4320b561052SJoerg Wunsch */ 4330b561052SJoerg Wunsch while (cgetnext(&buf, printcapdb) > 0) { 4340b561052SJoerg Wunsch if (ckqueue(buf) <= 0) { 4350b561052SJoerg Wunsch free(buf); 4360b561052SJoerg Wunsch continue; /* no work to do for this printer */ 4370b561052SJoerg Wunsch } 4380b561052SJoerg Wunsch for (cp = buf; *cp; cp++) 4390b561052SJoerg Wunsch if (*cp == '|' || *cp == ':') { 4400b561052SJoerg Wunsch *cp = '\0'; 4410b561052SJoerg Wunsch break; 4420b561052SJoerg Wunsch } 4430b561052SJoerg Wunsch if (lflag) 4440b561052SJoerg Wunsch syslog(LOG_INFO, "work for %s", buf); 4450b561052SJoerg Wunsch if ((pid = fork()) < 0) { 4460b561052SJoerg Wunsch syslog(LOG_WARNING, "startup: cannot fork"); 4470b561052SJoerg Wunsch mcleanup(0); 4480b561052SJoerg Wunsch } 4490b561052SJoerg Wunsch if (!pid) { 4500b561052SJoerg Wunsch printer = buf; 4510b561052SJoerg Wunsch cgetclose(); 4520b561052SJoerg Wunsch printjob(); 4530b561052SJoerg Wunsch /* NOTREACHED */ 4540b561052SJoerg Wunsch } 4550b561052SJoerg Wunsch else free(buf); 4560b561052SJoerg Wunsch } 4570b561052SJoerg Wunsch } 4580b561052SJoerg Wunsch 4590b561052SJoerg Wunsch /* 4600b561052SJoerg Wunsch * Make sure there's some work to do before forking off a child 4610b561052SJoerg Wunsch */ 4620b561052SJoerg Wunsch static int 4630b561052SJoerg Wunsch ckqueue(cap) 4640b561052SJoerg Wunsch char *cap; 4650b561052SJoerg Wunsch { 4660b561052SJoerg Wunsch register struct dirent *d; 4670b561052SJoerg Wunsch DIR *dirp; 4680b561052SJoerg Wunsch char *spooldir; 4690b561052SJoerg Wunsch 4700b561052SJoerg Wunsch if (cgetstr(cap, "sd", &spooldir) == -1) 4710b561052SJoerg Wunsch spooldir = _PATH_DEFSPOOL; 4720b561052SJoerg Wunsch if ((dirp = opendir(spooldir)) == NULL) 4730b561052SJoerg Wunsch return (-1); 4740b561052SJoerg Wunsch while ((d = readdir(dirp)) != NULL) { 4750b561052SJoerg Wunsch if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 4760b561052SJoerg Wunsch continue; /* daemon control files only */ 4770b561052SJoerg Wunsch closedir(dirp); 4780b561052SJoerg Wunsch return (1); /* found something */ 4790b561052SJoerg Wunsch } 4800b561052SJoerg Wunsch closedir(dirp); 4810b561052SJoerg Wunsch return (0); 4820b561052SJoerg Wunsch } 4830b561052SJoerg Wunsch 4840b561052SJoerg Wunsch #define DUMMY ":nobody::" 4850b561052SJoerg Wunsch 4860b561052SJoerg Wunsch /* 4870b561052SJoerg Wunsch * Check to see if the from host has access to the line printer. 4880b561052SJoerg Wunsch */ 4890b561052SJoerg Wunsch static void 4900b561052SJoerg Wunsch chkhost(f) 4910b561052SJoerg Wunsch struct sockaddr_in *f; 4920b561052SJoerg Wunsch { 4930b561052SJoerg Wunsch register struct hostent *hp; 4940b561052SJoerg Wunsch register FILE *hostf; 4950b561052SJoerg Wunsch int first = 1; 4960b561052SJoerg Wunsch extern char *inet_ntoa(); 4970b561052SJoerg Wunsch 4980b561052SJoerg Wunsch f->sin_port = ntohs(f->sin_port); 4990b561052SJoerg Wunsch if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED) 5000b561052SJoerg Wunsch fatal("Malformed from address"); 5010b561052SJoerg Wunsch 5020b561052SJoerg Wunsch /* Need real hostname for temporary filenames */ 5030b561052SJoerg Wunsch hp = gethostbyaddr((char *)&f->sin_addr, 5040b561052SJoerg Wunsch sizeof(struct in_addr), f->sin_family); 5050b561052SJoerg Wunsch if (hp == NULL) 5060b561052SJoerg Wunsch fatal("Host name for your address (%s) unknown", 5070b561052SJoerg Wunsch inet_ntoa(f->sin_addr)); 5080b561052SJoerg Wunsch 5090b561052SJoerg Wunsch (void) strncpy(fromb, hp->h_name, sizeof(fromb)); 5100b561052SJoerg Wunsch from[sizeof(fromb) - 1] = '\0'; 5110b561052SJoerg Wunsch from = fromb; 5120b561052SJoerg Wunsch 5130b561052SJoerg Wunsch hostf = fopen(_PATH_HOSTSEQUIV, "r"); 5140b561052SJoerg Wunsch again: 5150b561052SJoerg Wunsch if (hostf) { 5160b561052SJoerg Wunsch if (__ivaliduser(hostf, f->sin_addr.s_addr, 5170b561052SJoerg Wunsch DUMMY, DUMMY) == 0) { 5180b561052SJoerg Wunsch (void) fclose(hostf); 5190b561052SJoerg Wunsch return; 5200b561052SJoerg Wunsch } 5210b561052SJoerg Wunsch (void) fclose(hostf); 5220b561052SJoerg Wunsch } 5230b561052SJoerg Wunsch if (first == 1) { 5240b561052SJoerg Wunsch first = 0; 5250b561052SJoerg Wunsch hostf = fopen(_PATH_HOSTSLPD, "r"); 5260b561052SJoerg Wunsch goto again; 5270b561052SJoerg Wunsch } 5280b561052SJoerg Wunsch fatal("Your host does not have line printer access"); 5290b561052SJoerg Wunsch /*NOTREACHED*/ 5300b561052SJoerg Wunsch } 5310b561052SJoerg Wunsch 5320b561052SJoerg Wunsch 5330b561052SJoerg Wunsch 5340b561052SJoerg Wunsch 5350b561052SJoerg Wunsch 5360b561052SJoerg Wunsch 5370b561052SJoerg Wunsch 5380b561052SJoerg Wunsch 5390b561052SJoerg Wunsch 5400b561052SJoerg Wunsch 5410b561052SJoerg Wunsch 5420b561052SJoerg Wunsch 543