122426Sdist /*
222426Sdist  * Copyright (c) 1983 Regents of the University of California.
334203Sbostic  * All rights reserved.
434203Sbostic  *
542801Sbostic  * %sccs.include.redist.c%
622426Sdist  */
722426Sdist 
813952Ssam #ifndef lint
9*55470Sbostic static char sccsid[] = "@(#)common.c	5.8 (Berkeley) 07/21/92";
1034203Sbostic #endif /* not lint */
1113952Ssam 
12*55470Sbostic #include <sys/param.h>
13*55470Sbostic #include <sys/stat.h>
14*55470Sbostic 
15*55470Sbostic #include <sys/socket.h>
16*55470Sbostic #include <netinet/in.h>
17*55470Sbostic #include <netdb.h>
18*55470Sbostic 
19*55470Sbostic #include <dirent.h>
20*55470Sbostic #include <errno.h>
21*55470Sbostic #include <unistd.h>
22*55470Sbostic #include <stdlib.h>
23*55470Sbostic #include <stdio.h>
24*55470Sbostic #include <string.h>
25*55470Sbostic #include "lp.h"
26*55470Sbostic 
2712117Sralph /*
2812117Sralph  * Routines and data common to all the line printer functions.
2912117Sralph  */
3012117Sralph 
3112117Sralph int	DU;		/* daeomon user-id */
3212117Sralph int	MX;		/* maximum number of blocks to copy */
3313170Sralph int	MC;		/* maximum number of copies allowed */
3412117Sralph char	*LP;		/* line printer device name */
3512117Sralph char	*RM;		/* remote machine name */
3612117Sralph char	*RP;		/* remote printer name */
3712117Sralph char	*LO;		/* lock file name */
3812117Sralph char	*ST;		/* status file name */
3912117Sralph char	*SD;		/* spool directory */
4012117Sralph char	*AF;		/* accounting file */
4112117Sralph char	*LF;		/* log file for error messages */
4212117Sralph char	*OF;		/* name of output filter (created once) */
4312117Sralph char	*IF;		/* name of input filter (created per job) */
4412433Sralph char	*RF;		/* name of fortran text filter (per job) */
4512117Sralph char	*TF;		/* name of troff filter (per job) */
4613235Sralph char	*NF;		/* name of ditroff filter (per job) */
4712117Sralph char	*DF;		/* name of tex filter (per job) */
4812117Sralph char	*GF;		/* name of graph(1G) filter (per job) */
4912117Sralph char	*VF;		/* name of vplot filter (per job) */
5012117Sralph char	*CF;		/* name of cifplot filter (per job) */
5112117Sralph char	*PF;		/* name of vrast filter (per job) */
5212117Sralph char	*FF;		/* form feed string */
5312117Sralph char	*TR;		/* trailer string to be output when Q empties */
5413170Sralph short	SC;		/* suppress multiple copies */
5512117Sralph short	SF;		/* suppress FF on each print job */
5612117Sralph short	SH;		/* suppress header page */
5712117Sralph short	SB;		/* short banner instead of normal header */
5818128Sralph short	HL;		/* print header last */
5912117Sralph short	RW;		/* open LP for reading and writing */
6012117Sralph short	PW;		/* page width */
6112117Sralph short	PL;		/* page length */
6212433Sralph short	PX;		/* page width in pixels */
6312433Sralph short	PY;		/* page length in pixels */
6412117Sralph short	BR;		/* baud rate if lp is a tty */
6513170Sralph int	FC;		/* flags to clear if lp is a tty */
6613170Sralph int	FS;		/* flags to set if lp is a tty */
6713170Sralph int	XC;		/* flags to clear for local mode */
6813170Sralph int	XS;		/* flags to set for local mode */
6912433Sralph short	RS;		/* restricted to those with local accounts */
7012117Sralph 
7112117Sralph char	line[BUFSIZ];
7212117Sralph char	pbuf[BUFSIZ/2];	/* buffer for printcap strings */
7312117Sralph char	*bp = pbuf;	/* pointer into pbuf for pgetent() */
7412117Sralph char	*name;		/* program name */
7512117Sralph char	*printer;	/* printer name */
76*55470Sbostic 			/* host machine name */
77*55470Sbostic char	host[MAXHOSTNAMELEN];
7812117Sralph char	*from = host;	/* client's machine name */
7938736Stef int	sendtorem;	/* are we sending to a remote? */
8012117Sralph 
81*55470Sbostic static int compar __P((const void *, const void *));
82*55470Sbostic 
8312117Sralph /*
8412117Sralph  * Create a connection to the remote printer server.
8512117Sralph  * Most of this code comes from rcmd.c.
8612117Sralph  */
87*55470Sbostic int
8812528Sralph getport(rhost)
8912528Sralph 	char *rhost;
9012117Sralph {
9112117Sralph 	struct hostent *hp;
9212117Sralph 	struct servent *sp;
9312117Sralph 	struct sockaddr_in sin;
9412117Sralph 	int s, timo = 1, lport = IPPORT_RESERVED - 1;
9512874Sralph 	int err;
9612117Sralph 
9712117Sralph 	/*
9812117Sralph 	 * Get the host address and port number to connect to.
9912117Sralph 	 */
10012528Sralph 	if (rhost == NULL)
10112117Sralph 		fatal("no remote host to connect to");
10212528Sralph 	hp = gethostbyname(rhost);
10312117Sralph 	if (hp == NULL)
10412528Sralph 		fatal("unknown host %s", rhost);
10512117Sralph 	sp = getservbyname("printer", "tcp");
10612117Sralph 	if (sp == NULL)
10712117Sralph 		fatal("printer/tcp: unknown service");
10812117Sralph 	bzero((char *)&sin, sizeof(sin));
10912117Sralph 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
11012117Sralph 	sin.sin_family = hp->h_addrtype;
11112117Sralph 	sin.sin_port = sp->s_port;
11212117Sralph 
11312117Sralph 	/*
11412117Sralph 	 * Try connecting to the server.
11512117Sralph 	 */
11612117Sralph retry:
11712117Sralph 	s = rresvport(&lport);
11812117Sralph 	if (s < 0)
11912117Sralph 		return(-1);
12046910Sbostic 	if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
12112874Sralph 		err = errno;
12212874Sralph 		(void) close(s);
12312874Sralph 		errno = err;
12412117Sralph 		if (errno == EADDRINUSE) {
12512117Sralph 			lport--;
12612117Sralph 			goto retry;
12712117Sralph 		}
12812117Sralph 		if (errno == ECONNREFUSED && timo <= 16) {
12912117Sralph 			sleep(timo);
13012117Sralph 			timo *= 2;
13112117Sralph 			goto retry;
13212117Sralph 		}
13312117Sralph 		return(-1);
13412117Sralph 	}
13512117Sralph 	return(s);
13612117Sralph }
13712117Sralph 
13812117Sralph /*
13912117Sralph  * Getline reads a line from the control file cfp, removes tabs, converts
14012117Sralph  *  new-line to null and leaves it in line.
14112117Sralph  * Returns 0 at EOF or the number of characters read.
14212117Sralph  */
143*55470Sbostic int
14412117Sralph getline(cfp)
14512117Sralph 	FILE *cfp;
14612117Sralph {
14712117Sralph 	register int linel = 0;
14812117Sralph 	register char *lp = line;
14912117Sralph 	register c;
15012117Sralph 
15112117Sralph 	while ((c = getc(cfp)) != '\n') {
15212117Sralph 		if (c == EOF)
15312117Sralph 			return(0);
15412117Sralph 		if (c == '\t') {
15512117Sralph 			do {
15612117Sralph 				*lp++ = ' ';
15712117Sralph 				linel++;
15812117Sralph 			} while ((linel & 07) != 0);
15912117Sralph 			continue;
16012117Sralph 		}
16112117Sralph 		*lp++ = c;
16212117Sralph 		linel++;
16312117Sralph 	}
16412117Sralph 	*lp++ = '\0';
16512117Sralph 	return(linel);
16612117Sralph }
16712117Sralph 
16812117Sralph /*
16912117Sralph  * Scan the current directory and make a list of daemon files sorted by
17012117Sralph  * creation time.
17112117Sralph  * Return the number of entries and a pointer to the list.
17212117Sralph  */
173*55470Sbostic int
17412117Sralph getq(namelist)
17512117Sralph 	struct queue *(*namelist[]);
17612117Sralph {
177*55470Sbostic 	register struct dirent *d;
17812117Sralph 	register struct queue *q, **queue;
17912117Sralph 	register int nitems;
18012117Sralph 	struct stat stbuf;
18112117Sralph 	DIR *dirp;
18246910Sbostic 	int arraysz;
18312117Sralph 
18413170Sralph 	if ((dirp = opendir(SD)) == NULL)
18512117Sralph 		return(-1);
18612117Sralph 	if (fstat(dirp->dd_fd, &stbuf) < 0)
18712874Sralph 		goto errdone;
18812117Sralph 
18912117Sralph 	/*
19012117Sralph 	 * Estimate the array size by taking the size of the directory file
19112117Sralph 	 * and dividing it by a multiple of the minimum size entry.
19212117Sralph 	 */
19312117Sralph 	arraysz = (stbuf.st_size / 24);
19412117Sralph 	queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
19512117Sralph 	if (queue == NULL)
19612874Sralph 		goto errdone;
19712117Sralph 
19812117Sralph 	nitems = 0;
19912117Sralph 	while ((d = readdir(dirp)) != NULL) {
20012117Sralph 		if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
20112117Sralph 			continue;	/* daemon control files only */
20212117Sralph 		if (stat(d->d_name, &stbuf) < 0)
20312117Sralph 			continue;	/* Doesn't exist */
20412117Sralph 		q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
20512117Sralph 		if (q == NULL)
20612874Sralph 			goto errdone;
20712117Sralph 		q->q_time = stbuf.st_mtime;
20812117Sralph 		strcpy(q->q_name, d->d_name);
20912117Sralph 		/*
21012117Sralph 		 * Check to make sure the array has space left and
21112117Sralph 		 * realloc the maximum size.
21212117Sralph 		 */
21312117Sralph 		if (++nitems > arraysz) {
21412117Sralph 			queue = (struct queue **)realloc((char *)queue,
21512117Sralph 				(stbuf.st_size/12) * sizeof(struct queue *));
21612117Sralph 			if (queue == NULL)
21712874Sralph 				goto errdone;
21812117Sralph 		}
21912117Sralph 		queue[nitems-1] = q;
22012117Sralph 	}
22112117Sralph 	closedir(dirp);
22212117Sralph 	if (nitems)
22312117Sralph 		qsort(queue, nitems, sizeof(struct queue *), compar);
22412117Sralph 	*namelist = queue;
22512117Sralph 	return(nitems);
22612874Sralph 
22712874Sralph errdone:
22812874Sralph 	closedir(dirp);
22912874Sralph 	return(-1);
23012117Sralph }
23112117Sralph 
23212117Sralph /*
23312117Sralph  * Compare modification times.
23412117Sralph  */
235*55470Sbostic static int
23612117Sralph compar(p1, p2)
237*55470Sbostic 	const void *p1, *p2;
23812117Sralph {
239*55470Sbostic 	if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time)
24012117Sralph 		return(-1);
241*55470Sbostic 	if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time)
24212117Sralph 		return(1);
24312117Sralph 	return(0);
24412117Sralph }
24512117Sralph 
24638736Stef /*
24738736Stef  * Figure out whether the local machine is the same
24838736Stef  * as the remote machine (RM) entry (if it exists).
24938736Stef  */
25038736Stef char *
25138736Stef checkremote()
25238736Stef {
25338736Stef 	char name[MAXHOSTNAMELEN];
25438736Stef 	register struct hostent *hp;
25538736Stef 	static char errbuf[128];
25638736Stef 
25738736Stef 	sendtorem = 0;	/* assume printer is local */
25838736Stef 	if (RM != (char *)NULL) {
25938736Stef 		/* get the official name of the local host */
26038736Stef 		gethostname(name, sizeof(name));
26138736Stef 		name[sizeof(name)-1] = '\0';
26238736Stef 		hp = gethostbyname(name);
26338736Stef 		if (hp == (struct hostent *) NULL) {
264*55470Sbostic 		    (void) snprintf(errbuf, sizeof(errbuf),
26538736Stef 			"unable to get official name for local machine %s",
26638736Stef 			name);
26738736Stef 		    return errbuf;
26838736Stef 		} else (void) strcpy(name, hp->h_name);
26938736Stef 
27038736Stef 		/* get the official name of RM */
27138736Stef 		hp = gethostbyname(RM);
27238736Stef 		if (hp == (struct hostent *) NULL) {
273*55470Sbostic 		    (void) snprintf(errbuf, sizeof(errbuf),
27438736Stef 			"unable to get official name for remote machine %s",
27538736Stef 			RM);
27638736Stef 		    return errbuf;
27738736Stef 		}
27838736Stef 
27938736Stef 		/*
28038736Stef 		 * if the two hosts are not the same,
28138736Stef 		 * then the printer must be remote.
28238736Stef 		 */
28338736Stef 		if (strcmp(name, hp->h_name) != 0)
28438736Stef 			sendtorem = 1;
28538736Stef 	}
28638736Stef 	return (char *)0;
28738736Stef }
28838736Stef 
289*55470Sbostic #if __STDC__
290*55470Sbostic #include <stdarg.h>
291*55470Sbostic #else
292*55470Sbostic #include <varargs.h>
293*55470Sbostic #endif
294*55470Sbostic 
295*55470Sbostic void
296*55470Sbostic #if __STDC__
297*55470Sbostic fatal(const char *msg, ...)
298*55470Sbostic #else
299*55470Sbostic fatal(msg, va_alist)
30012117Sralph 	char *msg;
301*55470Sbostic         va_dcl
302*55470Sbostic #endif
30312117Sralph {
304*55470Sbostic 	va_list ap;
305*55470Sbostic #if __STDC__
306*55470Sbostic 	va_start(ap, msg);
307*55470Sbostic #else
308*55470Sbostic 	va_start(ap);
309*55470Sbostic #endif
31012117Sralph 	if (from != host)
311*55470Sbostic 		(void)printf("%s: ", host);
312*55470Sbostic 	(void)printf("%s: ", name);
31312117Sralph 	if (printer)
314*55470Sbostic 		(void)printf("%s: ", printer);
315*55470Sbostic 	(void)vprintf(msg, ap);
316*55470Sbostic 	va_end(ap);
317*55470Sbostic 	(void)putchar('\n');
31812117Sralph 	exit(1);
31912117Sralph }
320