Home | History | Annotate | Line # | Download | only in lpd
lpd.c revision 1.1.1.2
      1      1.1  cgd /*
      2  1.1.1.2  cgd  * Copyright (c) 1983, 1993, 1994
      3  1.1.1.2  cgd  *	The Regents of the University of California.  All rights reserved.
      4  1.1.1.2  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.1.1.2  cgd static char copyright[] =
     37  1.1.1.2  cgd "@(#) Copyright (c) 1983, 1993, 1994\n\
     38  1.1.1.2  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.1.1.2  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.1.1.2  cgd #include <sys/param.h>
     75  1.1.1.2  cgd #include <sys/wait.h>
     76  1.1.1.2  cgd #include <sys/types.h>
     77  1.1.1.2  cgd #include <sys/socket.h>
     78  1.1.1.2  cgd #include <sys/un.h>
     79  1.1.1.2  cgd #include <sys/stat.h>
     80  1.1.1.2  cgd #include <netinet/in.h>
     81  1.1.1.2  cgd 
     82  1.1.1.2  cgd #include <netdb.h>
     83  1.1.1.2  cgd #include <unistd.h>
     84  1.1.1.2  cgd #include <syslog.h>
     85  1.1.1.2  cgd #include <signal.h>
     86  1.1.1.2  cgd #include <errno.h>
     87  1.1.1.2  cgd #include <fcntl.h>
     88  1.1.1.2  cgd #include <dirent.h>
     89  1.1.1.2  cgd #include <stdio.h>
     90  1.1.1.2  cgd #include <stdlib.h>
     91  1.1.1.2  cgd #include <string.h>
     92  1.1.1.2  cgd #include <ctype.h>
     93      1.1  cgd #include "lp.h"
     94  1.1.1.2  cgd #include "lp.local.h"
     95      1.1  cgd #include "pathnames.h"
     96  1.1.1.2  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.1.1.2  cgd static void       reapchild __P((int));
    102  1.1.1.2  cgd static void       mcleanup __P((int));
    103  1.1.1.2  cgd static void       doit __P((void));
    104  1.1.1.2  cgd static void       startup __P((void));
    105  1.1.1.2  cgd static void       chkhost __P((struct sockaddr_in *));
    106      1.1  cgd 
    107  1.1.1.2  cgd int
    108      1.1  cgd main(argc, argv)
    109      1.1  cgd 	int argc;
    110      1.1  cgd 	char **argv;
    111      1.1  cgd {
    112  1.1.1.2  cgd 	int f, funix, finet, options, fromlen;
    113  1.1.1.2  cgd 	fd_set defreadfds;
    114  1.1.1.2  cgd 	struct sockaddr_un un, fromunix;
    115      1.1  cgd 	struct sockaddr_in sin, frominet;
    116      1.1  cgd 	int omask, lfd;
    117      1.1  cgd 
    118  1.1.1.2  cgd 	options = 0;
    119      1.1  cgd 	gethostname(host, sizeof(host));
    120      1.1  cgd 	name = argv[0];
    121      1.1  cgd 
    122      1.1  cgd 	while (--argc > 0) {
    123      1.1  cgd 		argv++;
    124      1.1  cgd 		if (argv[0][0] == '-')
    125      1.1  cgd 			switch (argv[0][1]) {
    126      1.1  cgd 			case 'd':
    127      1.1  cgd 				options |= SO_DEBUG;
    128      1.1  cgd 				break;
    129      1.1  cgd 			case 'l':
    130      1.1  cgd 				lflag++;
    131      1.1  cgd 				break;
    132      1.1  cgd 			}
    133      1.1  cgd 	}
    134      1.1  cgd 
    135      1.1  cgd #ifndef DEBUG
    136      1.1  cgd 	/*
    137      1.1  cgd 	 * Set up standard environment by detaching from the parent.
    138      1.1  cgd 	 */
    139      1.1  cgd 	daemon(0, 0);
    140      1.1  cgd #endif
    141      1.1  cgd 
    142      1.1  cgd 	openlog("lpd", LOG_PID, LOG_LPR);
    143  1.1.1.2  cgd 	syslog(LOG_INFO, "restarted");
    144      1.1  cgd 	(void) umask(0);
    145      1.1  cgd 	lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644);
    146      1.1  cgd 	if (lfd < 0) {
    147      1.1  cgd 		syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
    148      1.1  cgd 		exit(1);
    149      1.1  cgd 	}
    150      1.1  cgd 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
    151      1.1  cgd 		if (errno == EWOULDBLOCK)	/* active deamon present */
    152      1.1  cgd 			exit(0);
    153      1.1  cgd 		syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
    154      1.1  cgd 		exit(1);
    155      1.1  cgd 	}
    156      1.1  cgd 	ftruncate(lfd, 0);
    157      1.1  cgd 	/*
    158      1.1  cgd 	 * write process id for others to know
    159      1.1  cgd 	 */
    160      1.1  cgd 	sprintf(line, "%u\n", getpid());
    161      1.1  cgd 	f = strlen(line);
    162      1.1  cgd 	if (write(lfd, line, f) != f) {
    163      1.1  cgd 		syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
    164      1.1  cgd 		exit(1);
    165      1.1  cgd 	}
    166      1.1  cgd 	signal(SIGCHLD, reapchild);
    167      1.1  cgd 	/*
    168      1.1  cgd 	 * Restart all the printers.
    169      1.1  cgd 	 */
    170      1.1  cgd 	startup();
    171      1.1  cgd 	(void) unlink(_PATH_SOCKETNAME);
    172      1.1  cgd 	funix = socket(AF_UNIX, SOCK_STREAM, 0);
    173      1.1  cgd 	if (funix < 0) {
    174      1.1  cgd 		syslog(LOG_ERR, "socket: %m");
    175      1.1  cgd 		exit(1);
    176      1.1  cgd 	}
    177      1.1  cgd #define	mask(s)	(1 << ((s) - 1))
    178      1.1  cgd 	omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
    179      1.1  cgd 	signal(SIGHUP, mcleanup);
    180      1.1  cgd 	signal(SIGINT, mcleanup);
    181      1.1  cgd 	signal(SIGQUIT, mcleanup);
    182      1.1  cgd 	signal(SIGTERM, mcleanup);
    183  1.1.1.2  cgd 	memset(&un, 0, sizeof(un));
    184  1.1.1.2  cgd 	un.sun_family = AF_UNIX;
    185  1.1.1.2  cgd 	strcpy(un.sun_path, _PATH_SOCKETNAME);
    186  1.1.1.2  cgd #ifndef SUN_LEN
    187  1.1.1.2  cgd #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
    188  1.1.1.2  cgd #endif
    189  1.1.1.2  cgd 	if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) {
    190      1.1  cgd 		syslog(LOG_ERR, "ubind: %m");
    191      1.1  cgd 		exit(1);
    192      1.1  cgd 	}
    193      1.1  cgd 	sigsetmask(omask);
    194  1.1.1.2  cgd 	FD_ZERO(&defreadfds);
    195  1.1.1.2  cgd 	FD_SET(funix, &defreadfds);
    196      1.1  cgd 	listen(funix, 5);
    197      1.1  cgd 	finet = socket(AF_INET, SOCK_STREAM, 0);
    198      1.1  cgd 	if (finet >= 0) {
    199      1.1  cgd 		struct servent *sp;
    200      1.1  cgd 
    201      1.1  cgd 		if (options & SO_DEBUG)
    202      1.1  cgd 			if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) {
    203      1.1  cgd 				syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
    204  1.1.1.2  cgd 				mcleanup(0);
    205      1.1  cgd 			}
    206      1.1  cgd 		sp = getservbyname("printer", "tcp");
    207      1.1  cgd 		if (sp == NULL) {
    208      1.1  cgd 			syslog(LOG_ERR, "printer/tcp: unknown service");
    209  1.1.1.2  cgd 			mcleanup(0);
    210      1.1  cgd 		}
    211  1.1.1.2  cgd 		memset(&sin, 0, sizeof(sin));
    212      1.1  cgd 		sin.sin_family = AF_INET;
    213      1.1  cgd 		sin.sin_port = sp->s_port;
    214      1.1  cgd 		if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    215      1.1  cgd 			syslog(LOG_ERR, "bind: %m");
    216  1.1.1.2  cgd 			mcleanup(0);
    217      1.1  cgd 		}
    218  1.1.1.2  cgd 		FD_SET(finet, &defreadfds);
    219      1.1  cgd 		listen(finet, 5);
    220      1.1  cgd 	}
    221      1.1  cgd 	/*
    222      1.1  cgd 	 * Main loop: accept, do a request, continue.
    223      1.1  cgd 	 */
    224  1.1.1.2  cgd 	memset(&frominet, 0, sizeof(frominet));
    225  1.1.1.2  cgd 	memset(&fromunix, 0, sizeof(fromunix));
    226      1.1  cgd 	for (;;) {
    227  1.1.1.2  cgd 		int domain, nfds, s;
    228  1.1.1.2  cgd 		fd_set readfds;
    229      1.1  cgd 
    230  1.1.1.2  cgd 		FD_COPY(&defreadfds, &readfds);
    231      1.1  cgd 		nfds = select(20, &readfds, 0, 0, 0);
    232      1.1  cgd 		if (nfds <= 0) {
    233      1.1  cgd 			if (nfds < 0 && errno != EINTR)
    234      1.1  cgd 				syslog(LOG_WARNING, "select: %m");
    235      1.1  cgd 			continue;
    236      1.1  cgd 		}
    237  1.1.1.2  cgd 		if (FD_ISSET(funix, &readfds)) {
    238      1.1  cgd 			domain = AF_UNIX, fromlen = sizeof(fromunix);
    239      1.1  cgd 			s = accept(funix,
    240      1.1  cgd 			    (struct sockaddr *)&fromunix, &fromlen);
    241  1.1.1.2  cgd 		} else /* if (FD_ISSET(finet, &readfds)) */  {
    242      1.1  cgd 			domain = AF_INET, fromlen = sizeof(frominet);
    243      1.1  cgd 			s = accept(finet,
    244      1.1  cgd 			    (struct sockaddr *)&frominet, &fromlen);
    245      1.1  cgd 		}
    246      1.1  cgd 		if (s < 0) {
    247      1.1  cgd 			if (errno != EINTR)
    248      1.1  cgd 				syslog(LOG_WARNING, "accept: %m");
    249      1.1  cgd 			continue;
    250      1.1  cgd 		}
    251      1.1  cgd 		if (fork() == 0) {
    252      1.1  cgd 			signal(SIGCHLD, SIG_IGN);
    253      1.1  cgd 			signal(SIGHUP, SIG_IGN);
    254      1.1  cgd 			signal(SIGINT, SIG_IGN);
    255      1.1  cgd 			signal(SIGQUIT, SIG_IGN);
    256      1.1  cgd 			signal(SIGTERM, SIG_IGN);
    257      1.1  cgd 			(void) close(funix);
    258      1.1  cgd 			(void) close(finet);
    259      1.1  cgd 			dup2(s, 1);
    260      1.1  cgd 			(void) close(s);
    261      1.1  cgd 			if (domain == AF_INET) {
    262      1.1  cgd 				from_remote = 1;
    263      1.1  cgd 				chkhost(&frominet);
    264      1.1  cgd 			} else
    265      1.1  cgd 				from_remote = 0;
    266      1.1  cgd 			doit();
    267      1.1  cgd 			exit(0);
    268      1.1  cgd 		}
    269      1.1  cgd 		(void) close(s);
    270      1.1  cgd 	}
    271      1.1  cgd }
    272      1.1  cgd 
    273  1.1.1.2  cgd static void
    274  1.1.1.2  cgd reapchild(signo)
    275  1.1.1.2  cgd 	int signo;
    276      1.1  cgd {
    277      1.1  cgd 	union wait status;
    278      1.1  cgd 
    279      1.1  cgd 	while (wait3((int *)&status, WNOHANG, 0) > 0)
    280      1.1  cgd 		;
    281      1.1  cgd }
    282      1.1  cgd 
    283  1.1.1.2  cgd static void
    284  1.1.1.2  cgd mcleanup(signo)
    285  1.1.1.2  cgd 	int signo;
    286      1.1  cgd {
    287      1.1  cgd 	if (lflag)
    288      1.1  cgd 		syslog(LOG_INFO, "exiting");
    289      1.1  cgd 	unlink(_PATH_SOCKETNAME);
    290      1.1  cgd 	exit(0);
    291      1.1  cgd }
    292      1.1  cgd 
    293      1.1  cgd /*
    294      1.1  cgd  * Stuff for handling job specifications
    295      1.1  cgd  */
    296      1.1  cgd char	*user[MAXUSERS];	/* users to process */
    297      1.1  cgd int	users;			/* # of users in user array */
    298      1.1  cgd int	requ[MAXREQUESTS];	/* job number of spool entries */
    299      1.1  cgd int	requests;		/* # of spool requests */
    300      1.1  cgd char	*person;		/* name of person doing lprm */
    301      1.1  cgd 
    302  1.1.1.2  cgd char	fromb[MAXHOSTNAMELEN];	/* buffer for client's machine name */
    303  1.1.1.2  cgd char	cbuf[BUFSIZ];		/* command line buffer */
    304      1.1  cgd char	*cmdnames[] = {
    305      1.1  cgd 	"null",
    306      1.1  cgd 	"printjob",
    307      1.1  cgd 	"recvjob",
    308      1.1  cgd 	"displayq short",
    309      1.1  cgd 	"displayq long",
    310      1.1  cgd 	"rmjob"
    311      1.1  cgd };
    312      1.1  cgd 
    313  1.1.1.2  cgd static void
    314      1.1  cgd doit()
    315      1.1  cgd {
    316      1.1  cgd 	register char *cp;
    317      1.1  cgd 	register int n;
    318      1.1  cgd 
    319      1.1  cgd 	for (;;) {
    320      1.1  cgd 		cp = cbuf;
    321      1.1  cgd 		do {
    322      1.1  cgd 			if (cp >= &cbuf[sizeof(cbuf) - 1])
    323      1.1  cgd 				fatal("Command line too long");
    324      1.1  cgd 			if ((n = read(1, cp, 1)) != 1) {
    325      1.1  cgd 				if (n < 0)
    326      1.1  cgd 					fatal("Lost connection");
    327      1.1  cgd 				return;
    328      1.1  cgd 			}
    329      1.1  cgd 		} while (*cp++ != '\n');
    330      1.1  cgd 		*--cp = '\0';
    331      1.1  cgd 		cp = cbuf;
    332      1.1  cgd 		if (lflag) {
    333      1.1  cgd 			if (*cp >= '\1' && *cp <= '\5')
    334      1.1  cgd 				syslog(LOG_INFO, "%s requests %s %s",
    335      1.1  cgd 					from, cmdnames[*cp], cp+1);
    336      1.1  cgd 			else
    337      1.1  cgd 				syslog(LOG_INFO, "bad request (%d) from %s",
    338      1.1  cgd 					*cp, from);
    339      1.1  cgd 		}
    340      1.1  cgd 		switch (*cp++) {
    341      1.1  cgd 		case '\1':	/* check the queue and print any jobs there */
    342      1.1  cgd 			printer = cp;
    343      1.1  cgd 			printjob();
    344      1.1  cgd 			break;
    345      1.1  cgd 		case '\2':	/* receive files to be queued */
    346      1.1  cgd 			if (!from_remote) {
    347      1.1  cgd 				syslog(LOG_INFO, "illegal request (%d)", *cp);
    348      1.1  cgd 				exit(1);
    349      1.1  cgd 			}
    350      1.1  cgd 			printer = cp;
    351      1.1  cgd 			recvjob();
    352      1.1  cgd 			break;
    353      1.1  cgd 		case '\3':	/* display the queue (short form) */
    354      1.1  cgd 		case '\4':	/* display the queue (long form) */
    355      1.1  cgd 			printer = cp;
    356      1.1  cgd 			while (*cp) {
    357      1.1  cgd 				if (*cp != ' ') {
    358      1.1  cgd 					cp++;
    359      1.1  cgd 					continue;
    360      1.1  cgd 				}
    361      1.1  cgd 				*cp++ = '\0';
    362      1.1  cgd 				while (isspace(*cp))
    363      1.1  cgd 					cp++;
    364      1.1  cgd 				if (*cp == '\0')
    365      1.1  cgd 					break;
    366      1.1  cgd 				if (isdigit(*cp)) {
    367      1.1  cgd 					if (requests >= MAXREQUESTS)
    368      1.1  cgd 						fatal("Too many requests");
    369      1.1  cgd 					requ[requests++] = atoi(cp);
    370      1.1  cgd 				} else {
    371      1.1  cgd 					if (users >= MAXUSERS)
    372      1.1  cgd 						fatal("Too many users");
    373      1.1  cgd 					user[users++] = cp;
    374      1.1  cgd 				}
    375      1.1  cgd 			}
    376      1.1  cgd 			displayq(cbuf[0] - '\3');
    377      1.1  cgd 			exit(0);
    378      1.1  cgd 		case '\5':	/* remove a job from the queue */
    379      1.1  cgd 			if (!from_remote) {
    380      1.1  cgd 				syslog(LOG_INFO, "illegal request (%d)", *cp);
    381      1.1  cgd 				exit(1);
    382      1.1  cgd 			}
    383      1.1  cgd 			printer = cp;
    384      1.1  cgd 			while (*cp && *cp != ' ')
    385      1.1  cgd 				cp++;
    386      1.1  cgd 			if (!*cp)
    387      1.1  cgd 				break;
    388      1.1  cgd 			*cp++ = '\0';
    389      1.1  cgd 			person = cp;
    390      1.1  cgd 			while (*cp) {
    391      1.1  cgd 				if (*cp != ' ') {
    392      1.1  cgd 					cp++;
    393      1.1  cgd 					continue;
    394      1.1  cgd 				}
    395      1.1  cgd 				*cp++ = '\0';
    396      1.1  cgd 				while (isspace(*cp))
    397      1.1  cgd 					cp++;
    398      1.1  cgd 				if (*cp == '\0')
    399      1.1  cgd 					break;
    400      1.1  cgd 				if (isdigit(*cp)) {
    401      1.1  cgd 					if (requests >= MAXREQUESTS)
    402      1.1  cgd 						fatal("Too many requests");
    403      1.1  cgd 					requ[requests++] = atoi(cp);
    404      1.1  cgd 				} else {
    405      1.1  cgd 					if (users >= MAXUSERS)
    406      1.1  cgd 						fatal("Too many users");
    407      1.1  cgd 					user[users++] = cp;
    408      1.1  cgd 				}
    409      1.1  cgd 			}
    410      1.1  cgd 			rmjob();
    411      1.1  cgd 			break;
    412      1.1  cgd 		}
    413      1.1  cgd 		fatal("Illegal service request");
    414      1.1  cgd 	}
    415      1.1  cgd }
    416      1.1  cgd 
    417      1.1  cgd /*
    418      1.1  cgd  * Make a pass through the printcap database and start printing any
    419      1.1  cgd  * files left from the last time the machine went down.
    420      1.1  cgd  */
    421  1.1.1.2  cgd static void
    422      1.1  cgd startup()
    423      1.1  cgd {
    424  1.1.1.2  cgd 	char *buf;
    425      1.1  cgd 	register char *cp;
    426      1.1  cgd 	int pid;
    427      1.1  cgd 
    428      1.1  cgd 	/*
    429      1.1  cgd 	 * Restart the daemons.
    430      1.1  cgd 	 */
    431  1.1.1.2  cgd 	while (cgetnext(&buf, printcapdb) > 0) {
    432      1.1  cgd 		for (cp = buf; *cp; cp++)
    433      1.1  cgd 			if (*cp == '|' || *cp == ':') {
    434      1.1  cgd 				*cp = '\0';
    435      1.1  cgd 				break;
    436      1.1  cgd 			}
    437      1.1  cgd 		if ((pid = fork()) < 0) {
    438      1.1  cgd 			syslog(LOG_WARNING, "startup: cannot fork");
    439  1.1.1.2  cgd 			mcleanup(0);
    440      1.1  cgd 		}
    441      1.1  cgd 		if (!pid) {
    442  1.1.1.2  cgd 			printer = buf;
    443  1.1.1.2  cgd 			cgetclose();
    444      1.1  cgd 			printjob();
    445      1.1  cgd 		}
    446      1.1  cgd 	}
    447      1.1  cgd }
    448      1.1  cgd 
    449      1.1  cgd #define DUMMY ":nobody::"
    450      1.1  cgd 
    451      1.1  cgd /*
    452      1.1  cgd  * Check to see if the from host has access to the line printer.
    453      1.1  cgd  */
    454  1.1.1.2  cgd static void
    455      1.1  cgd chkhost(f)
    456      1.1  cgd 	struct sockaddr_in *f;
    457      1.1  cgd {
    458      1.1  cgd 	register struct hostent *hp;
    459      1.1  cgd 	register FILE *hostf;
    460      1.1  cgd 	int first = 1;
    461      1.1  cgd 	extern char *inet_ntoa();
    462      1.1  cgd 
    463      1.1  cgd 	f->sin_port = ntohs(f->sin_port);
    464      1.1  cgd 	if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED)
    465      1.1  cgd 		fatal("Malformed from address");
    466  1.1.1.2  cgd 
    467  1.1.1.2  cgd 	/* Need real hostname for temporary filenames */
    468      1.1  cgd 	hp = gethostbyaddr((char *)&f->sin_addr,
    469      1.1  cgd 	    sizeof(struct in_addr), f->sin_family);
    470  1.1.1.2  cgd 	if (hp == NULL)
    471      1.1  cgd 		fatal("Host name for your address (%s) unknown",
    472      1.1  cgd 			inet_ntoa(f->sin_addr));
    473      1.1  cgd 
    474  1.1.1.2  cgd 	(void) strncpy(fromb, hp->h_name, sizeof(fromb));
    475  1.1.1.2  cgd 	from[sizeof(fromb) - 1] = '\0';
    476      1.1  cgd 	from = fromb;
    477      1.1  cgd 
    478      1.1  cgd 	hostf = fopen(_PATH_HOSTSEQUIV, "r");
    479      1.1  cgd again:
    480      1.1  cgd 	if (hostf) {
    481  1.1.1.2  cgd 		if (__ivaliduser(hostf, f->sin_addr.s_addr,
    482  1.1.1.2  cgd 		    DUMMY, DUMMY) == 0) {
    483      1.1  cgd 			(void) fclose(hostf);
    484      1.1  cgd 			return;
    485      1.1  cgd 		}
    486      1.1  cgd 		(void) fclose(hostf);
    487      1.1  cgd 	}
    488      1.1  cgd 	if (first == 1) {
    489      1.1  cgd 		first = 0;
    490      1.1  cgd 		hostf = fopen(_PATH_HOSTSLPD, "r");
    491      1.1  cgd 		goto again;
    492      1.1  cgd 	}
    493      1.1  cgd 	fatal("Your host does not have line printer access");
    494  1.1.1.2  cgd 	/*NOTREACHED*/
    495      1.1  cgd }
    496  1.1.1.2  cgd 
    497  1.1.1.2  cgd 
    498  1.1.1.2  cgd 
    499  1.1.1.2  cgd 
    500  1.1.1.2  cgd 
    501  1.1.1.2  cgd 
    502  1.1.1.2  cgd 
    503  1.1.1.2  cgd 
    504  1.1.1.2  cgd 
    505  1.1.1.2  cgd 
    506  1.1.1.2  cgd 
    507  1.1.1.2  cgd 
    508