xref: /freebsd/usr.sbin/lpr/lpd/lpd.c (revision 0b561052dfd9d0992c8bfd08ef46df9b8d272373)
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