122426Sdist /*
222426Sdist  * Copyright (c) 1983 Regents of the University of California.
334203Sbostic  * All rights reserved.
434203Sbostic  *
534203Sbostic  * Redistribution and use in source and binary forms are permitted
634936Sbostic  * provided that the above copyright notice and this paragraph are
734936Sbostic  * duplicated in all such forms and that any documentation,
834936Sbostic  * advertising materials, and other materials related to such
934936Sbostic  * distribution and use acknowledge that the software was developed
1034936Sbostic  * by the University of California, Berkeley.  The name of the
1134936Sbostic  * University may not be used to endorse or promote products derived
1234936Sbostic  * from this software without specific prior written permission.
1334936Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434936Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534936Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622426Sdist  */
1722426Sdist 
1813952Ssam #ifndef lint
19*38736Stef static char sccsid[] = "@(#)common.c	5.5 (Berkeley) 08/22/89";
2034203Sbostic #endif /* not lint */
2113952Ssam 
2212117Sralph /*
2312117Sralph  * Routines and data common to all the line printer functions.
2412117Sralph  */
2512117Sralph 
2612117Sralph #include "lp.h"
2712117Sralph 
2812117Sralph int	DU;		/* daeomon user-id */
2912117Sralph int	MX;		/* maximum number of blocks to copy */
3013170Sralph int	MC;		/* maximum number of copies allowed */
3112117Sralph char	*LP;		/* line printer device name */
3212117Sralph char	*RM;		/* remote machine name */
3312117Sralph char	*RP;		/* remote printer name */
3412117Sralph char	*LO;		/* lock file name */
3512117Sralph char	*ST;		/* status file name */
3612117Sralph char	*SD;		/* spool directory */
3712117Sralph char	*AF;		/* accounting file */
3812117Sralph char	*LF;		/* log file for error messages */
3912117Sralph char	*OF;		/* name of output filter (created once) */
4012117Sralph char	*IF;		/* name of input filter (created per job) */
4112433Sralph char	*RF;		/* name of fortran text filter (per job) */
4212117Sralph char	*TF;		/* name of troff filter (per job) */
4313235Sralph char	*NF;		/* name of ditroff filter (per job) */
4412117Sralph char	*DF;		/* name of tex filter (per job) */
4512117Sralph char	*GF;		/* name of graph(1G) filter (per job) */
4612117Sralph char	*VF;		/* name of vplot filter (per job) */
4712117Sralph char	*CF;		/* name of cifplot filter (per job) */
4812117Sralph char	*PF;		/* name of vrast filter (per job) */
4912117Sralph char	*FF;		/* form feed string */
5012117Sralph char	*TR;		/* trailer string to be output when Q empties */
5113170Sralph short	SC;		/* suppress multiple copies */
5212117Sralph short	SF;		/* suppress FF on each print job */
5312117Sralph short	SH;		/* suppress header page */
5412117Sralph short	SB;		/* short banner instead of normal header */
5518128Sralph short	HL;		/* print header last */
5612117Sralph short	RW;		/* open LP for reading and writing */
5712117Sralph short	PW;		/* page width */
5812117Sralph short	PL;		/* page length */
5912433Sralph short	PX;		/* page width in pixels */
6012433Sralph short	PY;		/* page length in pixels */
6112117Sralph short	BR;		/* baud rate if lp is a tty */
6213170Sralph int	FC;		/* flags to clear if lp is a tty */
6313170Sralph int	FS;		/* flags to set if lp is a tty */
6413170Sralph int	XC;		/* flags to clear for local mode */
6513170Sralph int	XS;		/* flags to set for local mode */
6612433Sralph short	RS;		/* restricted to those with local accounts */
6712117Sralph 
6812117Sralph char	line[BUFSIZ];
6912117Sralph char	pbuf[BUFSIZ/2];	/* buffer for printcap strings */
7012117Sralph char	*bp = pbuf;	/* pointer into pbuf for pgetent() */
7112117Sralph char	*name;		/* program name */
7212117Sralph char	*printer;	/* printer name */
7312117Sralph char	host[32];	/* host machine name */
7412117Sralph char	*from = host;	/* client's machine name */
75*38736Stef int	sendtorem;	/* are we sending to a remote? */
7612117Sralph 
7712117Sralph /*
7812117Sralph  * Create a connection to the remote printer server.
7912117Sralph  * Most of this code comes from rcmd.c.
8012117Sralph  */
8112528Sralph getport(rhost)
8212528Sralph 	char *rhost;
8312117Sralph {
8412117Sralph 	struct hostent *hp;
8512117Sralph 	struct servent *sp;
8612117Sralph 	struct sockaddr_in sin;
8712117Sralph 	int s, timo = 1, lport = IPPORT_RESERVED - 1;
8812874Sralph 	int err;
8912117Sralph 
9012117Sralph 	/*
9112117Sralph 	 * Get the host address and port number to connect to.
9212117Sralph 	 */
9312528Sralph 	if (rhost == NULL)
9412117Sralph 		fatal("no remote host to connect to");
9512528Sralph 	hp = gethostbyname(rhost);
9612117Sralph 	if (hp == NULL)
9712528Sralph 		fatal("unknown host %s", rhost);
9812117Sralph 	sp = getservbyname("printer", "tcp");
9912117Sralph 	if (sp == NULL)
10012117Sralph 		fatal("printer/tcp: unknown service");
10112117Sralph 	bzero((char *)&sin, sizeof(sin));
10212117Sralph 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
10312117Sralph 	sin.sin_family = hp->h_addrtype;
10412117Sralph 	sin.sin_port = sp->s_port;
10512117Sralph 
10612117Sralph 	/*
10712117Sralph 	 * Try connecting to the server.
10812117Sralph 	 */
10912117Sralph retry:
11012117Sralph 	s = rresvport(&lport);
11112117Sralph 	if (s < 0)
11212117Sralph 		return(-1);
113*38736Stef 	if (connect(s, (caddr_t)&sin, sizeof(sin)) < 0) {
11412874Sralph 		err = errno;
11512874Sralph 		(void) close(s);
11612874Sralph 		errno = err;
11712117Sralph 		if (errno == EADDRINUSE) {
11812117Sralph 			lport--;
11912117Sralph 			goto retry;
12012117Sralph 		}
12112117Sralph 		if (errno == ECONNREFUSED && timo <= 16) {
12212117Sralph 			sleep(timo);
12312117Sralph 			timo *= 2;
12412117Sralph 			goto retry;
12512117Sralph 		}
12612117Sralph 		return(-1);
12712117Sralph 	}
12812117Sralph 	return(s);
12912117Sralph }
13012117Sralph 
13112117Sralph /*
13212117Sralph  * Getline reads a line from the control file cfp, removes tabs, converts
13312117Sralph  *  new-line to null and leaves it in line.
13412117Sralph  * Returns 0 at EOF or the number of characters read.
13512117Sralph  */
13612117Sralph getline(cfp)
13712117Sralph 	FILE *cfp;
13812117Sralph {
13912117Sralph 	register int linel = 0;
14012117Sralph 	register char *lp = line;
14112117Sralph 	register c;
14212117Sralph 
14312117Sralph 	while ((c = getc(cfp)) != '\n') {
14412117Sralph 		if (c == EOF)
14512117Sralph 			return(0);
14612117Sralph 		if (c == '\t') {
14712117Sralph 			do {
14812117Sralph 				*lp++ = ' ';
14912117Sralph 				linel++;
15012117Sralph 			} while ((linel & 07) != 0);
15112117Sralph 			continue;
15212117Sralph 		}
15312117Sralph 		*lp++ = c;
15412117Sralph 		linel++;
15512117Sralph 	}
15612117Sralph 	*lp++ = '\0';
15712117Sralph 	return(linel);
15812117Sralph }
15912117Sralph 
16012117Sralph /*
16112117Sralph  * Scan the current directory and make a list of daemon files sorted by
16212117Sralph  * creation time.
16312117Sralph  * Return the number of entries and a pointer to the list.
16412117Sralph  */
16512117Sralph getq(namelist)
16612117Sralph 	struct queue *(*namelist[]);
16712117Sralph {
16812117Sralph 	register struct direct *d;
16912117Sralph 	register struct queue *q, **queue;
17012117Sralph 	register int nitems;
17112117Sralph 	struct stat stbuf;
17212117Sralph 	int arraysz, compar();
17312117Sralph 	DIR *dirp;
17412117Sralph 
17513170Sralph 	if ((dirp = opendir(SD)) == NULL)
17612117Sralph 		return(-1);
17712117Sralph 	if (fstat(dirp->dd_fd, &stbuf) < 0)
17812874Sralph 		goto errdone;
17912117Sralph 
18012117Sralph 	/*
18112117Sralph 	 * Estimate the array size by taking the size of the directory file
18212117Sralph 	 * and dividing it by a multiple of the minimum size entry.
18312117Sralph 	 */
18412117Sralph 	arraysz = (stbuf.st_size / 24);
18512117Sralph 	queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
18612117Sralph 	if (queue == NULL)
18712874Sralph 		goto errdone;
18812117Sralph 
18912117Sralph 	nitems = 0;
19012117Sralph 	while ((d = readdir(dirp)) != NULL) {
19112117Sralph 		if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
19212117Sralph 			continue;	/* daemon control files only */
19312117Sralph 		if (stat(d->d_name, &stbuf) < 0)
19412117Sralph 			continue;	/* Doesn't exist */
19512117Sralph 		q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
19612117Sralph 		if (q == NULL)
19712874Sralph 			goto errdone;
19812117Sralph 		q->q_time = stbuf.st_mtime;
19912117Sralph 		strcpy(q->q_name, d->d_name);
20012117Sralph 		/*
20112117Sralph 		 * Check to make sure the array has space left and
20212117Sralph 		 * realloc the maximum size.
20312117Sralph 		 */
20412117Sralph 		if (++nitems > arraysz) {
20512117Sralph 			queue = (struct queue **)realloc((char *)queue,
20612117Sralph 				(stbuf.st_size/12) * sizeof(struct queue *));
20712117Sralph 			if (queue == NULL)
20812874Sralph 				goto errdone;
20912117Sralph 		}
21012117Sralph 		queue[nitems-1] = q;
21112117Sralph 	}
21212117Sralph 	closedir(dirp);
21312117Sralph 	if (nitems)
21412117Sralph 		qsort(queue, nitems, sizeof(struct queue *), compar);
21512117Sralph 	*namelist = queue;
21612117Sralph 	return(nitems);
21712874Sralph 
21812874Sralph errdone:
21912874Sralph 	closedir(dirp);
22012874Sralph 	return(-1);
22112117Sralph }
22212117Sralph 
22312117Sralph /*
22412117Sralph  * Compare modification times.
22512117Sralph  */
22612117Sralph static
22712117Sralph compar(p1, p2)
22812117Sralph 	register struct queue **p1, **p2;
22912117Sralph {
23012117Sralph 	if ((*p1)->q_time < (*p2)->q_time)
23112117Sralph 		return(-1);
23212117Sralph 	if ((*p1)->q_time > (*p2)->q_time)
23312117Sralph 		return(1);
23412117Sralph 	return(0);
23512117Sralph }
23612117Sralph 
237*38736Stef /*
238*38736Stef  * Figure out whether the local machine is the same
239*38736Stef  * as the remote machine (RM) entry (if it exists).
240*38736Stef  */
241*38736Stef char *
242*38736Stef checkremote()
243*38736Stef {
244*38736Stef 	char name[MAXHOSTNAMELEN];
245*38736Stef 	register struct hostent *hp;
246*38736Stef 	static char errbuf[128];
247*38736Stef 
248*38736Stef 	sendtorem = 0;	/* assume printer is local */
249*38736Stef 	if (RM != (char *)NULL) {
250*38736Stef 		/* get the official name of the local host */
251*38736Stef 		gethostname(name, sizeof(name));
252*38736Stef 		name[sizeof(name)-1] = '\0';
253*38736Stef 		hp = gethostbyname(name);
254*38736Stef 		if (hp == (struct hostent *) NULL) {
255*38736Stef 		    (void) sprintf(errbuf,
256*38736Stef 			"unable to get official name for local machine %s",
257*38736Stef 			name);
258*38736Stef 		    return errbuf;
259*38736Stef 		} else (void) strcpy(name, hp->h_name);
260*38736Stef 
261*38736Stef 		/* get the official name of RM */
262*38736Stef 		hp = gethostbyname(RM);
263*38736Stef 		if (hp == (struct hostent *) NULL) {
264*38736Stef 		    (void) sprintf(errbuf,
265*38736Stef 			"unable to get official name for remote machine %s",
266*38736Stef 			RM);
267*38736Stef 		    return errbuf;
268*38736Stef 		}
269*38736Stef 
270*38736Stef 		/*
271*38736Stef 		 * if the two hosts are not the same,
272*38736Stef 		 * then the printer must be remote.
273*38736Stef 		 */
274*38736Stef 		if (strcmp(name, hp->h_name) != 0)
275*38736Stef 			sendtorem = 1;
276*38736Stef 	}
277*38736Stef 	return (char *)0;
278*38736Stef }
279*38736Stef 
28012117Sralph /*VARARGS1*/
28112117Sralph fatal(msg, a1, a2, a3)
28212117Sralph 	char *msg;
28312117Sralph {
28412117Sralph 	if (from != host)
28512117Sralph 		printf("%s: ", host);
28612117Sralph 	printf("%s: ", name);
28712117Sralph 	if (printer)
28812117Sralph 		printf("%s: ", printer);
28912117Sralph 	printf(msg, a1, a2, a3);
29012117Sralph 	putchar('\n');
29112117Sralph 	exit(1);
29212117Sralph }
293