1*12433Sralph /*	common.c	4.2	83/05/13	*/
212117Sralph /*
312117Sralph  * Routines and data common to all the line printer functions.
412117Sralph  */
512117Sralph 
612117Sralph #include "lp.h"
712117Sralph 
812117Sralph int	DU;		/* daeomon user-id */
912117Sralph int	MX;		/* maximum number of blocks to copy */
1012117Sralph char	*LP;		/* line printer device name */
1112117Sralph char	*RM;		/* remote machine name */
1212117Sralph char	*RP;		/* remote printer name */
1312117Sralph char	*LO;		/* lock file name */
1412117Sralph char	*ST;		/* status file name */
1512117Sralph char	*SD;		/* spool directory */
1612117Sralph char	*AF;		/* accounting file */
1712117Sralph char	*LF;		/* log file for error messages */
1812117Sralph char	*OF;		/* name of output filter (created once) */
1912117Sralph char	*IF;		/* name of input filter (created per job) */
20*12433Sralph char	*RF;		/* name of fortran text filter (per job) */
2112117Sralph char	*TF;		/* name of troff filter (per job) */
2212117Sralph char	*DF;		/* name of tex filter (per job) */
2312117Sralph char	*GF;		/* name of graph(1G) filter (per job) */
2412117Sralph char	*VF;		/* name of vplot filter (per job) */
2512117Sralph char	*CF;		/* name of cifplot filter (per job) */
2612117Sralph char	*PF;		/* name of vrast filter (per job) */
2712117Sralph char	*FF;		/* form feed string */
2812117Sralph char	*TR;		/* trailer string to be output when Q empties */
2912117Sralph short	SF;		/* suppress FF on each print job */
3012117Sralph short	SH;		/* suppress header page */
3112117Sralph short	SB;		/* short banner instead of normal header */
3212117Sralph short	RW;		/* open LP for reading and writing */
3312117Sralph short	PW;		/* page width */
3412117Sralph short	PL;		/* page length */
35*12433Sralph short	PX;		/* page width in pixels */
36*12433Sralph short	PY;		/* page length in pixels */
3712117Sralph short	BR;		/* baud rate if lp is a tty */
3812117Sralph short	FC;		/* flags to clear if lp is a tty */
3912117Sralph short	FS;		/* flags to set if lp is a tty */
4012117Sralph short	XC;		/* flags to clear for local mode */
4112117Sralph short	XS;		/* flags to set for local mode */
42*12433Sralph short	RS;		/* restricted to those with local accounts */
4312117Sralph 
4412117Sralph char	line[BUFSIZ];
4512117Sralph char	pbuf[BUFSIZ/2];	/* buffer for printcap strings */
4612117Sralph char	*bp = pbuf;	/* pointer into pbuf for pgetent() */
4712117Sralph char	*name;		/* program name */
4812117Sralph char	*printer;	/* printer name */
4912117Sralph char	host[32];	/* host machine name */
5012117Sralph char	*from = host;	/* client's machine name */
5112117Sralph 
5212117Sralph /*
5312117Sralph  * Create a connection to the remote printer server.
5412117Sralph  * Most of this code comes from rcmd.c.
5512117Sralph  */
5612117Sralph getport()
5712117Sralph {
5812117Sralph 	struct hostent *hp;
5912117Sralph 	struct servent *sp;
6012117Sralph 	struct sockaddr_in sin;
6112117Sralph 	int s, timo = 1, lport = IPPORT_RESERVED - 1;
6212117Sralph 
6312117Sralph 	/*
6412117Sralph 	 * Get the host address and port number to connect to.
6512117Sralph 	 */
6612117Sralph 	if (RM == NULL)
6712117Sralph 		fatal("no remote host to connect to");
6812117Sralph 	hp = gethostbyname(RM);
6912117Sralph 	if (hp == NULL)
7012117Sralph 		fatal("unknown host %s", RM);
7112117Sralph 	sp = getservbyname("printer", "tcp");
7212117Sralph 	if (sp == NULL)
7312117Sralph 		fatal("printer/tcp: unknown service");
7412117Sralph 	bzero((char *)&sin, sizeof(sin));
7512117Sralph 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
7612117Sralph 	sin.sin_family = hp->h_addrtype;
7712117Sralph 	sin.sin_port = sp->s_port;
7812117Sralph 
7912117Sralph 	/*
8012117Sralph 	 * Try connecting to the server.
8112117Sralph 	 */
8212117Sralph retry:
8312117Sralph 	s = rresvport(&lport);
8412117Sralph 	if (s < 0)
8512117Sralph 		return(-1);
8612117Sralph 	if (connect(s, (caddr_t)&sin, sizeof(sin), 0) < 0) {
8712117Sralph 		if (errno == EADDRINUSE) {
8812117Sralph 			close(s);
8912117Sralph 			lport--;
9012117Sralph 			goto retry;
9112117Sralph 		}
9212117Sralph 		if (errno == ECONNREFUSED && timo <= 16) {
9312117Sralph 			(void) close(s);
9412117Sralph 			sleep(timo);
9512117Sralph 			timo *= 2;
9612117Sralph 			goto retry;
9712117Sralph 		}
9812117Sralph 		return(-1);
9912117Sralph 	}
10012117Sralph 	return(s);
10112117Sralph }
10212117Sralph 
10312117Sralph rresvport(alport)
10412117Sralph 	int *alport;
10512117Sralph {
10612117Sralph 	struct sockaddr_in sin;
10712117Sralph 	int s;
10812117Sralph 
10912117Sralph 	sin.sin_family = AF_INET;
11012117Sralph 	sin.sin_addr.s_addr = 0;
11112117Sralph 	s = socket(AF_INET, SOCK_STREAM, 0);
11212117Sralph 	if (s < 0)
11312117Sralph 		return(-1);
11412117Sralph 	for (;;) {
11512117Sralph 		sin.sin_port = htons((u_short) *alport);
11612117Sralph 		if (bind(s, (caddr_t)&sin, sizeof(sin), 0) >= 0)
11712117Sralph 			return(s);
11812117Sralph 		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL)
11912117Sralph 			return(-1);
12012117Sralph 		(*alport)--;
12112117Sralph 		if (*alport == IPPORT_RESERVED/2) {
12212117Sralph 			printf("%s: All ports in use\n", name);
12312117Sralph 			return(-1);
12412117Sralph 		}
12512117Sralph 	}
12612117Sralph }
12712117Sralph 
12812117Sralph /*
12912117Sralph  * Getline reads a line from the control file cfp, removes tabs, converts
13012117Sralph  *  new-line to null and leaves it in line.
13112117Sralph  * Returns 0 at EOF or the number of characters read.
13212117Sralph  */
13312117Sralph getline(cfp)
13412117Sralph 	FILE *cfp;
13512117Sralph {
13612117Sralph 	register int linel = 0;
13712117Sralph 	register char *lp = line;
13812117Sralph 	register c;
13912117Sralph 
14012117Sralph 	while ((c = getc(cfp)) != '\n') {
14112117Sralph 		if (c == EOF)
14212117Sralph 			return(0);
14312117Sralph 		if (c == '\t') {
14412117Sralph 			do {
14512117Sralph 				*lp++ = ' ';
14612117Sralph 				linel++;
14712117Sralph 			} while ((linel & 07) != 0);
14812117Sralph 			continue;
14912117Sralph 		}
15012117Sralph 		*lp++ = c;
15112117Sralph 		linel++;
15212117Sralph 	}
15312117Sralph 	*lp++ = '\0';
15412117Sralph 	return(linel);
15512117Sralph }
15612117Sralph 
15712117Sralph /*
15812117Sralph  * Scan the current directory and make a list of daemon files sorted by
15912117Sralph  * creation time.
16012117Sralph  * Return the number of entries and a pointer to the list.
16112117Sralph  */
16212117Sralph getq(namelist)
16312117Sralph 	struct queue *(*namelist[]);
16412117Sralph {
16512117Sralph 	register struct direct *d;
16612117Sralph 	register struct queue *q, **queue;
16712117Sralph 	register int nitems;
16812117Sralph 	struct stat stbuf;
16912117Sralph 	int arraysz, compar();
17012117Sralph 	DIR *dirp;
17112117Sralph 
17212117Sralph 	if ((dirp = opendir(".")) == NULL)
17312117Sralph 		return(-1);
17412117Sralph 	if (fstat(dirp->dd_fd, &stbuf) < 0)
17512117Sralph 		return(-1);
17612117Sralph 
17712117Sralph 	/*
17812117Sralph 	 * Estimate the array size by taking the size of the directory file
17912117Sralph 	 * and dividing it by a multiple of the minimum size entry.
18012117Sralph 	 */
18112117Sralph 	arraysz = (stbuf.st_size / 24);
18212117Sralph 	queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
18312117Sralph 	if (queue == NULL)
18412117Sralph 		return(-1);
18512117Sralph 
18612117Sralph 	nitems = 0;
18712117Sralph 	while ((d = readdir(dirp)) != NULL) {
18812117Sralph 		if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
18912117Sralph 			continue;	/* daemon control files only */
19012117Sralph 		if (stat(d->d_name, &stbuf) < 0)
19112117Sralph 			continue;	/* Doesn't exist */
19212117Sralph 		q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
19312117Sralph 		if (q == NULL)
19412117Sralph 			return(-1);
19512117Sralph 		q->q_time = stbuf.st_mtime;
19612117Sralph 		strcpy(q->q_name, d->d_name);
19712117Sralph 		/*
19812117Sralph 		 * Check to make sure the array has space left and
19912117Sralph 		 * realloc the maximum size.
20012117Sralph 		 */
20112117Sralph 		if (++nitems > arraysz) {
20212117Sralph 			queue = (struct queue **)realloc((char *)queue,
20312117Sralph 				(stbuf.st_size/12) * sizeof(struct queue *));
20412117Sralph 			if (queue == NULL)
20512117Sralph 				return(-1);
20612117Sralph 		}
20712117Sralph 		queue[nitems-1] = q;
20812117Sralph 	}
20912117Sralph 	closedir(dirp);
21012117Sralph 	if (nitems)
21112117Sralph 		qsort(queue, nitems, sizeof(struct queue *), compar);
21212117Sralph 	*namelist = queue;
21312117Sralph 	return(nitems);
21412117Sralph }
21512117Sralph 
21612117Sralph /*
21712117Sralph  * Compare modification times.
21812117Sralph  */
21912117Sralph static
22012117Sralph compar(p1, p2)
22112117Sralph 	register struct queue **p1, **p2;
22212117Sralph {
22312117Sralph 	if ((*p1)->q_time < (*p2)->q_time)
22412117Sralph 		return(-1);
22512117Sralph 	if ((*p1)->q_time > (*p2)->q_time)
22612117Sralph 		return(1);
22712117Sralph 	return(0);
22812117Sralph }
22912117Sralph 
23012117Sralph /*VARARGS1*/
23112117Sralph fatal(msg, a1, a2, a3)
23212117Sralph 	char *msg;
23312117Sralph {
23412117Sralph 	if (from != host)
23512117Sralph 		printf("%s: ", host);
23612117Sralph 	printf("%s: ", name);
23712117Sralph 	if (printer)
23812117Sralph 		printf("%s: ", printer);
23912117Sralph 	printf(msg, a1, a2, a3);
24012117Sralph 	putchar('\n');
24112117Sralph 	exit(1);
24212117Sralph }
24312117Sralph 
24412117Sralph fatalerror(msg)
24512117Sralph 	char *msg;
24612117Sralph {
24712117Sralph 	extern int sys_nerr;
24812117Sralph 	extern char *sys_errlist[];
24912117Sralph 
25012117Sralph 	printf("%s: ", name);
25112117Sralph 	if (*msg)
25212117Sralph 		printf("%s: ", msg);
25312117Sralph 	fputs(errno < sys_nerr ? sys_errlist[errno] : "Unknown error" , stdout);
25412117Sralph 	putchar('\n');
25512117Sralph 	exit(1);
25612117Sralph }
257