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