Home | History | Annotate | Line # | Download | only in lpd
lpd.c revision 1.5
      1  1.1      cgd /*
      2  1.4      cgd  * Copyright (c) 1983, 1993, 1994
      3  1.4      cgd  *	The Regents of the University of California.  All rights reserved.
      4  1.4      cgd  *
      5  1.1      cgd  *
      6  1.1      cgd  * Redistribution and use in source and binary forms, with or without
      7  1.1      cgd  * modification, are permitted provided that the following conditions
      8  1.1      cgd  * are met:
      9  1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     10  1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     11  1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     13  1.1      cgd  *    documentation and/or other materials provided with the distribution.
     14  1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     15  1.1      cgd  *    must display the following acknowledgement:
     16  1.1      cgd  *	This product includes software developed by the University of
     17  1.1      cgd  *	California, Berkeley and its contributors.
     18  1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     19  1.1      cgd  *    may be used to endorse or promote products derived from this software
     20  1.1      cgd  *    without specific prior written permission.
     21  1.1      cgd  *
     22  1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23  1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26  1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  1.1      cgd  * SUCH DAMAGE.
     33  1.1      cgd  */
     34  1.1      cgd 
     35  1.1      cgd #ifndef lint
     36  1.4      cgd static char copyright[] =
     37  1.4      cgd "@(#) Copyright (c) 1983, 1993, 1994\n\
     38  1.4      cgd 	The Regents of the University of California.  All rights reserved.\n";
     39  1.1      cgd #endif /* not lint */
     40  1.1      cgd 
     41  1.1      cgd #ifndef lint
     42  1.4      cgd static char sccsid[] = "@(#)lpd.c	8.4 (Berkeley) 4/17/94";
     43  1.1      cgd #endif /* not lint */
     44  1.1      cgd 
     45  1.1      cgd /*
     46  1.1      cgd  * lpd -- line printer daemon.
     47  1.1      cgd  *
     48  1.1      cgd  * Listen for a connection and perform the requested operation.
     49  1.1      cgd  * Operations are:
     50  1.1      cgd  *	\1printer\n
     51  1.1      cgd  *		check the queue for jobs and print any found.
     52  1.1      cgd  *	\2printer\n
     53  1.1      cgd  *		receive a job from another machine and queue it.
     54  1.1      cgd  *	\3printer [users ...] [jobs ...]\n
     55  1.1      cgd  *		return the current state of the queue (short form).
     56  1.1      cgd  *	\4printer [users ...] [jobs ...]\n
     57  1.1      cgd  *		return the current state of the queue (long form).
     58  1.1      cgd  *	\5printer person [users ...] [jobs ...]\n
     59  1.1      cgd  *		remove jobs from the queue.
     60  1.1      cgd  *
     61  1.1      cgd  * Strategy to maintain protected spooling area:
     62  1.1      cgd  *	1. Spooling area is writable only by daemon and spooling group
     63  1.1      cgd  *	2. lpr runs setuid root and setgrp spooling group; it uses
     64  1.1      cgd  *	   root to access any file it wants (verifying things before
     65  1.1      cgd  *	   with an access call) and group id to know how it should
     66  1.1      cgd  *	   set up ownership of files in the spooling area.
     67  1.1      cgd  *	3. Files in spooling area are owned by root, group spooling
     68  1.1      cgd  *	   group, with mode 660.
     69  1.1      cgd  *	4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to
     70  1.1      cgd  *	   access files and printer.  Users can't get to anything
     71  1.1      cgd  *	   w/o help of lpq and lprm programs.
     72  1.1      cgd  */
     73  1.1      cgd 
     74  1.4      cgd #include <sys/param.h>
     75  1.4      cgd #include <sys/wait.h>
     76  1.4      cgd #include <sys/types.h>
     77  1.4      cgd #include <sys/socket.h>
     78  1.4      cgd #include <sys/un.h>
     79  1.4      cgd #include <sys/stat.h>
     80  1.4      cgd #include <netinet/in.h>
     81  1.4      cgd 
     82  1.4      cgd #include <netdb.h>
     83  1.4      cgd #include <unistd.h>
     84  1.4      cgd #include <syslog.h>
     85  1.4      cgd #include <signal.h>
     86  1.4      cgd #include <errno.h>
     87  1.4      cgd #include <fcntl.h>
     88  1.4      cgd #include <dirent.h>
     89  1.4      cgd #include <stdio.h>
     90  1.4      cgd #include <stdlib.h>
     91  1.4      cgd #include <string.h>
     92  1.4      cgd #include <ctype.h>
     93  1.1      cgd #include "lp.h"
     94  1.4      cgd #include "lp.local.h"
     95  1.1      cgd #include "pathnames.h"
     96  1.4      cgd #include "extern.h"
     97  1.1      cgd 
     98  1.1      cgd int	lflag;				/* log requests flag */
     99  1.1      cgd int	from_remote;			/* from remote socket */
    100  1.1      cgd 
    101  1.4      cgd static void       reapchild __P((int));
    102  1.4      cgd static void       mcleanup __P((int));
    103  1.4      cgd static void       doit __P((void));
    104  1.4      cgd static void       startup __P((void));
    105  1.4      cgd static void       chkhost __P((struct sockaddr_in *));
    106  1.1      cgd 
    107  1.5  hpeyerl uid_t	uid, euid;
    108  1.5  hpeyerl 
    109  1.4      cgd int
    110  1.1      cgd main(argc, argv)
    111  1.1      cgd 	int argc;
    112  1.1      cgd 	char **argv;
    113  1.1      cgd {
    114  1.4      cgd 	int f, funix, finet, options, fromlen;
    115  1.4      cgd 	fd_set defreadfds;
    116  1.4      cgd 	struct sockaddr_un un, fromunix;
    117  1.1      cgd 	struct sockaddr_in sin, frominet;
    118  1.1      cgd 	int omask, lfd;
    119  1.1      cgd 
    120  1.5  hpeyerl 	euid = geteuid();	/* these shouldn't be different */
    121  1.5  hpeyerl 	uid = getuid();
    122  1.4      cgd 	options = 0;
    123  1.1      cgd 	gethostname(host, sizeof(host));
    124  1.1      cgd 	name = argv[0];
    125  1.1      cgd 
    126  1.1      cgd 	while (--argc > 0) {
    127  1.1      cgd 		argv++;
    128  1.1      cgd 		if (argv[0][0] == '-')
    129  1.1      cgd 			switch (argv[0][1]) {
    130  1.1      cgd 			case 'd':
    131  1.1      cgd 				options |= SO_DEBUG;
    132  1.1      cgd 				break;
    133  1.1      cgd 			case 'l':
    134  1.1      cgd 				lflag++;
    135  1.1      cgd 				break;
    136  1.1      cgd 			}
    137  1.1      cgd 	}
    138  1.1      cgd 
    139  1.1      cgd #ifndef DEBUG
    140  1.1      cgd 	/*
    141  1.1      cgd 	 * Set up standard environment by detaching from the parent.
    142  1.1      cgd 	 */
    143  1.1      cgd 	daemon(0, 0);
    144  1.1      cgd #endif
    145  1.1      cgd 
    146  1.1      cgd 	openlog("lpd", LOG_PID, LOG_LPR);
    147  1.4      cgd 	syslog(LOG_INFO, "restarted");
    148  1.1      cgd 	(void) umask(0);
    149  1.1      cgd 	lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644);
    150  1.1      cgd 	if (lfd < 0) {
    151  1.1      cgd 		syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
    152  1.1      cgd 		exit(1);
    153  1.1      cgd 	}
    154  1.1      cgd 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
    155  1.1      cgd 		if (errno == EWOULDBLOCK)	/* active deamon present */
    156  1.1      cgd 			exit(0);
    157  1.1      cgd 		syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
    158  1.1      cgd 		exit(1);
    159  1.1      cgd 	}
    160  1.1      cgd 	ftruncate(lfd, 0);
    161  1.1      cgd 	/*
    162  1.1      cgd 	 * write process id for others to know
    163  1.1      cgd 	 */
    164  1.1      cgd 	sprintf(line, "%u\n", getpid());
    165  1.1      cgd 	f = strlen(line);
    166  1.1      cgd 	if (write(lfd, line, f) != f) {
    167  1.1      cgd 		syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
    168  1.1      cgd 		exit(1);
    169  1.1      cgd 	}
    170  1.1      cgd 	signal(SIGCHLD, reapchild);
    171  1.1      cgd 	/*
    172  1.1      cgd 	 * Restart all the printers.
    173  1.1      cgd 	 */
    174  1.1      cgd 	startup();
    175  1.1      cgd 	(void) unlink(_PATH_SOCKETNAME);
    176  1.1      cgd 	funix = socket(AF_UNIX, SOCK_STREAM, 0);
    177  1.1      cgd 	if (funix < 0) {
    178  1.1      cgd 		syslog(LOG_ERR, "socket: %m");
    179  1.1      cgd 		exit(1);
    180  1.1      cgd 	}
    181  1.1      cgd #define	mask(s)	(1 << ((s) - 1))
    182  1.1      cgd 	omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
    183  1.1      cgd 	signal(SIGHUP, mcleanup);
    184  1.1      cgd 	signal(SIGINT, mcleanup);
    185  1.1      cgd 	signal(SIGQUIT, mcleanup);
    186  1.1      cgd 	signal(SIGTERM, mcleanup);
    187  1.4      cgd 	memset(&un, 0, sizeof(un));
    188  1.4      cgd 	un.sun_family = AF_UNIX;
    189  1.4      cgd 	strcpy(un.sun_path, _PATH_SOCKETNAME);
    190  1.4      cgd #ifndef SUN_LEN
    191  1.4      cgd #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
    192  1.4      cgd #endif
    193  1.4      cgd 	if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) {
    194  1.1      cgd 		syslog(LOG_ERR, "ubind: %m");
    195  1.1      cgd 		exit(1);
    196  1.1      cgd 	}
    197  1.1      cgd 	sigsetmask(omask);
    198  1.4      cgd 	FD_ZERO(&defreadfds);
    199  1.4      cgd 	FD_SET(funix, &defreadfds);
    200  1.1      cgd 	listen(funix, 5);
    201  1.1      cgd 	finet = socket(AF_INET, SOCK_STREAM, 0);
    202  1.1      cgd 	if (finet >= 0) {
    203  1.1      cgd 		struct servent *sp;
    204  1.1      cgd 
    205  1.1      cgd 		if (options & SO_DEBUG)
    206  1.1      cgd 			if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) {
    207  1.1      cgd 				syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
    208  1.4      cgd 				mcleanup(0);
    209  1.1      cgd 			}
    210  1.1      cgd 		sp = getservbyname("printer", "tcp");
    211  1.1      cgd 		if (sp == NULL) {
    212  1.1      cgd 			syslog(LOG_ERR, "printer/tcp: unknown service");
    213  1.4      cgd 			mcleanup(0);
    214  1.1      cgd 		}
    215  1.4      cgd 		memset(&sin, 0, sizeof(sin));
    216  1.1      cgd 		sin.sin_family = AF_INET;
    217  1.1      cgd 		sin.sin_port = sp->s_port;
    218  1.1      cgd 		if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    219  1.1      cgd 			syslog(LOG_ERR, "bind: %m");
    220  1.4      cgd 			mcleanup(0);
    221  1.1      cgd 		}
    222  1.4      cgd 		FD_SET(finet, &defreadfds);
    223  1.1      cgd 		listen(finet, 5);
    224  1.1      cgd 	}
    225  1.1      cgd 	/*
    226  1.1      cgd 	 * Main loop: accept, do a request, continue.
    227  1.1      cgd 	 */
    228  1.4      cgd 	memset(&frominet, 0, sizeof(frominet));
    229  1.4      cgd 	memset(&fromunix, 0, sizeof(fromunix));
    230  1.1      cgd 	for (;;) {
    231  1.4      cgd 		int domain, nfds, s;
    232  1.4      cgd 		fd_set readfds;
    233  1.1      cgd 
    234  1.4      cgd 		FD_COPY(&defreadfds, &readfds);
    235  1.1      cgd 		nfds = select(20, &readfds, 0, 0, 0);
    236  1.1      cgd 		if (nfds <= 0) {
    237  1.1      cgd 			if (nfds < 0 && errno != EINTR)
    238  1.1      cgd 				syslog(LOG_WARNING, "select: %m");
    239  1.1      cgd 			continue;
    240  1.1      cgd 		}
    241  1.4      cgd 		if (FD_ISSET(funix, &readfds)) {
    242  1.1      cgd 			domain = AF_UNIX, fromlen = sizeof(fromunix);
    243  1.1      cgd 			s = accept(funix,
    244  1.1      cgd 			    (struct sockaddr *)&fromunix, &fromlen);
    245  1.4      cgd 		} else /* if (FD_ISSET(finet, &readfds)) */  {
    246  1.1      cgd 			domain = AF_INET, fromlen = sizeof(frominet);
    247  1.1      cgd 			s = accept(finet,
    248  1.1      cgd 			    (struct sockaddr *)&frominet, &fromlen);
    249  1.1      cgd 		}
    250  1.1      cgd 		if (s < 0) {
    251  1.1      cgd 			if (errno != EINTR)
    252  1.1      cgd 				syslog(LOG_WARNING, "accept: %m");
    253  1.1      cgd 			continue;
    254  1.1      cgd 		}
    255  1.1      cgd 		if (fork() == 0) {
    256  1.1      cgd 			signal(SIGCHLD, SIG_IGN);
    257  1.1      cgd 			signal(SIGHUP, SIG_IGN);
    258  1.1      cgd 			signal(SIGINT, SIG_IGN);
    259  1.1      cgd 			signal(SIGQUIT, SIG_IGN);
    260  1.1      cgd 			signal(SIGTERM, SIG_IGN);
    261  1.1      cgd 			(void) close(funix);
    262  1.1      cgd 			(void) close(finet);
    263  1.1      cgd 			dup2(s, 1);
    264  1.1      cgd 			(void) close(s);
    265  1.1      cgd 			if (domain == AF_INET) {
    266  1.1      cgd 				from_remote = 1;
    267  1.1      cgd 				chkhost(&frominet);
    268  1.1      cgd 			} else
    269  1.1      cgd 				from_remote = 0;
    270  1.1      cgd 			doit();
    271  1.1      cgd 			exit(0);
    272  1.1      cgd 		}
    273  1.1      cgd 		(void) close(s);
    274  1.1      cgd 	}
    275  1.1      cgd }
    276  1.1      cgd 
    277  1.4      cgd static void
    278  1.4      cgd reapchild(signo)
    279  1.4      cgd 	int signo;
    280  1.1      cgd {
    281  1.1      cgd 	union wait status;
    282  1.1      cgd 
    283  1.1      cgd 	while (wait3((int *)&status, WNOHANG, 0) > 0)
    284  1.1      cgd 		;
    285  1.1      cgd }
    286  1.1      cgd 
    287  1.4      cgd static void
    288  1.4      cgd mcleanup(signo)
    289  1.4      cgd 	int signo;
    290  1.1      cgd {
    291  1.1      cgd 	if (lflag)
    292  1.1      cgd 		syslog(LOG_INFO, "exiting");
    293  1.1      cgd 	unlink(_PATH_SOCKETNAME);
    294  1.1      cgd 	exit(0);
    295  1.1      cgd }
    296  1.1      cgd 
    297  1.1      cgd /*
    298  1.1      cgd  * Stuff for handling job specifications
    299  1.1      cgd  */
    300  1.1      cgd char	*user[MAXUSERS];	/* users to process */
    301  1.1      cgd int	users;			/* # of users in user array */
    302  1.1      cgd int	requ[MAXREQUESTS];	/* job number of spool entries */
    303  1.1      cgd int	requests;		/* # of spool requests */
    304  1.1      cgd char	*person;		/* name of person doing lprm */
    305  1.1      cgd 
    306  1.4      cgd char	fromb[MAXHOSTNAMELEN];	/* buffer for client's machine name */
    307  1.4      cgd char	cbuf[BUFSIZ];		/* command line buffer */
    308  1.1      cgd char	*cmdnames[] = {
    309  1.1      cgd 	"null",
    310  1.1      cgd 	"printjob",
    311  1.1      cgd 	"recvjob",
    312  1.1      cgd 	"displayq short",
    313  1.1      cgd 	"displayq long",
    314  1.1      cgd 	"rmjob"
    315  1.1      cgd };
    316  1.1      cgd 
    317  1.4      cgd static void
    318  1.1      cgd doit()
    319  1.1      cgd {
    320  1.1      cgd 	register char *cp;
    321  1.1      cgd 	register int n;
    322  1.1      cgd 
    323  1.1      cgd 	for (;;) {
    324  1.1      cgd 		cp = cbuf;
    325  1.1      cgd 		do {
    326  1.1      cgd 			if (cp >= &cbuf[sizeof(cbuf) - 1])
    327  1.1      cgd 				fatal("Command line too long");
    328  1.1      cgd 			if ((n = read(1, cp, 1)) != 1) {
    329  1.1      cgd 				if (n < 0)
    330  1.1      cgd 					fatal("Lost connection");
    331  1.1      cgd 				return;
    332  1.1      cgd 			}
    333  1.1      cgd 		} while (*cp++ != '\n');
    334  1.1      cgd 		*--cp = '\0';
    335  1.1      cgd 		cp = cbuf;
    336  1.1      cgd 		if (lflag) {
    337  1.1      cgd 			if (*cp >= '\1' && *cp <= '\5')
    338  1.1      cgd 				syslog(LOG_INFO, "%s requests %s %s",
    339  1.1      cgd 					from, cmdnames[*cp], cp+1);
    340  1.1      cgd 			else
    341  1.1      cgd 				syslog(LOG_INFO, "bad request (%d) from %s",
    342  1.1      cgd 					*cp, from);
    343  1.1      cgd 		}
    344  1.1      cgd 		switch (*cp++) {
    345  1.1      cgd 		case '\1':	/* check the queue and print any jobs there */
    346  1.1      cgd 			printer = cp;
    347  1.1      cgd 			printjob();
    348  1.1      cgd 			break;
    349  1.1      cgd 		case '\2':	/* receive files to be queued */
    350  1.1      cgd 			if (!from_remote) {
    351  1.1      cgd 				syslog(LOG_INFO, "illegal request (%d)", *cp);
    352  1.1      cgd 				exit(1);
    353  1.1      cgd 			}
    354  1.1      cgd 			printer = cp;
    355  1.1      cgd 			recvjob();
    356  1.1      cgd 			break;
    357  1.1      cgd 		case '\3':	/* display the queue (short form) */
    358  1.1      cgd 		case '\4':	/* display the queue (long form) */
    359  1.1      cgd 			printer = cp;
    360  1.1      cgd 			while (*cp) {
    361  1.1      cgd 				if (*cp != ' ') {
    362  1.1      cgd 					cp++;
    363  1.1      cgd 					continue;
    364  1.1      cgd 				}
    365  1.1      cgd 				*cp++ = '\0';
    366  1.1      cgd 				while (isspace(*cp))
    367  1.1      cgd 					cp++;
    368  1.1      cgd 				if (*cp == '\0')
    369  1.1      cgd 					break;
    370  1.1      cgd 				if (isdigit(*cp)) {
    371  1.1      cgd 					if (requests >= MAXREQUESTS)
    372  1.1      cgd 						fatal("Too many requests");
    373  1.1      cgd 					requ[requests++] = atoi(cp);
    374  1.1      cgd 				} else {
    375  1.1      cgd 					if (users >= MAXUSERS)
    376  1.1      cgd 						fatal("Too many users");
    377  1.1      cgd 					user[users++] = cp;
    378  1.1      cgd 				}
    379  1.1      cgd 			}
    380  1.1      cgd 			displayq(cbuf[0] - '\3');
    381  1.1      cgd 			exit(0);
    382  1.1      cgd 		case '\5':	/* remove a job from the queue */
    383  1.1      cgd 			if (!from_remote) {
    384  1.1      cgd 				syslog(LOG_INFO, "illegal request (%d)", *cp);
    385  1.1      cgd 				exit(1);
    386  1.1      cgd 			}
    387  1.1      cgd 			printer = cp;
    388  1.1      cgd 			while (*cp && *cp != ' ')
    389  1.1      cgd 				cp++;
    390  1.1      cgd 			if (!*cp)
    391  1.1      cgd 				break;
    392  1.1      cgd 			*cp++ = '\0';
    393  1.1      cgd 			person = cp;
    394  1.1      cgd 			while (*cp) {
    395  1.1      cgd 				if (*cp != ' ') {
    396  1.1      cgd 					cp++;
    397  1.1      cgd 					continue;
    398  1.1      cgd 				}
    399  1.1      cgd 				*cp++ = '\0';
    400  1.1      cgd 				while (isspace(*cp))
    401  1.1      cgd 					cp++;
    402  1.1      cgd 				if (*cp == '\0')
    403  1.1      cgd 					break;
    404  1.1      cgd 				if (isdigit(*cp)) {
    405  1.1      cgd 					if (requests >= MAXREQUESTS)
    406  1.1      cgd 						fatal("Too many requests");
    407  1.1      cgd 					requ[requests++] = atoi(cp);
    408  1.1      cgd 				} else {
    409  1.1      cgd 					if (users >= MAXUSERS)
    410  1.1      cgd 						fatal("Too many users");
    411  1.1      cgd 					user[users++] = cp;
    412  1.1      cgd 				}
    413  1.1      cgd 			}
    414  1.1      cgd 			rmjob();
    415  1.1      cgd 			break;
    416  1.1      cgd 		}
    417  1.1      cgd 		fatal("Illegal service request");
    418  1.1      cgd 	}
    419  1.1      cgd }
    420  1.1      cgd 
    421  1.1      cgd /*
    422  1.1      cgd  * Make a pass through the printcap database and start printing any
    423  1.1      cgd  * files left from the last time the machine went down.
    424  1.1      cgd  */
    425  1.4      cgd static void
    426  1.1      cgd startup()
    427  1.1      cgd {
    428  1.4      cgd 	char *buf;
    429  1.1      cgd 	register char *cp;
    430  1.1      cgd 	int pid;
    431  1.1      cgd 
    432  1.1      cgd 	/*
    433  1.1      cgd 	 * Restart the daemons.
    434  1.1      cgd 	 */
    435  1.4      cgd 	while (cgetnext(&buf, printcapdb) > 0) {
    436  1.1      cgd 		for (cp = buf; *cp; cp++)
    437  1.1      cgd 			if (*cp == '|' || *cp == ':') {
    438  1.1      cgd 				*cp = '\0';
    439  1.1      cgd 				break;
    440  1.1      cgd 			}
    441  1.1      cgd 		if ((pid = fork()) < 0) {
    442  1.1      cgd 			syslog(LOG_WARNING, "startup: cannot fork");
    443  1.4      cgd 			mcleanup(0);
    444  1.1      cgd 		}
    445  1.1      cgd 		if (!pid) {
    446  1.4      cgd 			printer = buf;
    447  1.4      cgd 			cgetclose();
    448  1.1      cgd 			printjob();
    449  1.1      cgd 		}
    450  1.1      cgd 	}
    451  1.1      cgd }
    452  1.1      cgd 
    453  1.1      cgd #define DUMMY ":nobody::"
    454  1.1      cgd 
    455  1.1      cgd /*
    456  1.1      cgd  * Check to see if the from host has access to the line printer.
    457  1.1      cgd  */
    458  1.4      cgd static void
    459  1.1      cgd chkhost(f)
    460  1.1      cgd 	struct sockaddr_in *f;
    461  1.1      cgd {
    462  1.1      cgd 	register struct hostent *hp;
    463  1.1      cgd 	register FILE *hostf;
    464  1.1      cgd 	int first = 1;
    465  1.1      cgd 	extern char *inet_ntoa();
    466  1.1      cgd 
    467  1.1      cgd 	f->sin_port = ntohs(f->sin_port);
    468  1.1      cgd 	if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED)
    469  1.1      cgd 		fatal("Malformed from address");
    470  1.4      cgd 
    471  1.4      cgd 	/* Need real hostname for temporary filenames */
    472  1.1      cgd 	hp = gethostbyaddr((char *)&f->sin_addr,
    473  1.1      cgd 	    sizeof(struct in_addr), f->sin_family);
    474  1.4      cgd 	if (hp == NULL)
    475  1.1      cgd 		fatal("Host name for your address (%s) unknown",
    476  1.1      cgd 			inet_ntoa(f->sin_addr));
    477  1.1      cgd 
    478  1.4      cgd 	(void) strncpy(fromb, hp->h_name, sizeof(fromb));
    479  1.4      cgd 	from[sizeof(fromb) - 1] = '\0';
    480  1.1      cgd 	from = fromb;
    481  1.1      cgd 
    482  1.1      cgd 	hostf = fopen(_PATH_HOSTSEQUIV, "r");
    483  1.1      cgd again:
    484  1.1      cgd 	if (hostf) {
    485  1.4      cgd 		if (__ivaliduser(hostf, f->sin_addr.s_addr,
    486  1.4      cgd 		    DUMMY, DUMMY) == 0) {
    487  1.1      cgd 			(void) fclose(hostf);
    488  1.1      cgd 			return;
    489  1.1      cgd 		}
    490  1.1      cgd 		(void) fclose(hostf);
    491  1.1      cgd 	}
    492  1.1      cgd 	if (first == 1) {
    493  1.1      cgd 		first = 0;
    494  1.1      cgd 		hostf = fopen(_PATH_HOSTSLPD, "r");
    495  1.1      cgd 		goto again;
    496  1.1      cgd 	}
    497  1.1      cgd 	fatal("Your host does not have line printer access");
    498  1.4      cgd 	/*NOTREACHED*/
    499  1.1      cgd }
    500  1.4      cgd 
    501  1.4      cgd 
    502  1.4      cgd 
    503  1.4      cgd 
    504  1.4      cgd 
    505  1.4      cgd 
    506  1.4      cgd 
    507  1.4      cgd 
    508  1.4      cgd 
    509  1.4      cgd 
    510  1.4      cgd 
    511  1.4      cgd 
    512