1*12117Sralph /*	common.c	4.1	83/04/29	*/
2*12117Sralph /*
3*12117Sralph  * Routines and data common to all the line printer functions.
4*12117Sralph  */
5*12117Sralph 
6*12117Sralph #include "lp.h"
7*12117Sralph 
8*12117Sralph int	DU;		/* daeomon user-id */
9*12117Sralph int	MX;		/* maximum number of blocks to copy */
10*12117Sralph char	*LP;		/* line printer device name */
11*12117Sralph char	*RM;		/* remote machine name */
12*12117Sralph char	*RP;		/* remote printer name */
13*12117Sralph char	*LO;		/* lock file name */
14*12117Sralph char	*ST;		/* status file name */
15*12117Sralph char	*SD;		/* spool directory */
16*12117Sralph char	*AF;		/* accounting file */
17*12117Sralph char	*LF;		/* log file for error messages */
18*12117Sralph char	*OF;		/* name of output filter (created once) */
19*12117Sralph char	*IF;		/* name of input filter (created per job) */
20*12117Sralph char	*TF;		/* name of troff filter (per job) */
21*12117Sralph char	*DF;		/* name of tex filter (per job) */
22*12117Sralph char	*GF;		/* name of graph(1G) filter (per job) */
23*12117Sralph char	*VF;		/* name of vplot filter (per job) */
24*12117Sralph char	*CF;		/* name of cifplot filter (per job) */
25*12117Sralph char	*PF;		/* name of vrast filter (per job) */
26*12117Sralph char	*FF;		/* form feed string */
27*12117Sralph char	*TR;		/* trailer string to be output when Q empties */
28*12117Sralph short	SF;		/* suppress FF on each print job */
29*12117Sralph short	SH;		/* suppress header page */
30*12117Sralph short	SB;		/* short banner instead of normal header */
31*12117Sralph short	RW;		/* open LP for reading and writing */
32*12117Sralph short	PW;		/* page width */
33*12117Sralph short	PL;		/* page length */
34*12117Sralph short	BR;		/* baud rate if lp is a tty */
35*12117Sralph short	FC;		/* flags to clear if lp is a tty */
36*12117Sralph short	FS;		/* flags to set if lp is a tty */
37*12117Sralph short	XC;		/* flags to clear for local mode */
38*12117Sralph short	XS;		/* flags to set for local mode */
39*12117Sralph 
40*12117Sralph char	line[BUFSIZ];
41*12117Sralph char	pbuf[BUFSIZ/2];	/* buffer for printcap strings */
42*12117Sralph char	*bp = pbuf;	/* pointer into pbuf for pgetent() */
43*12117Sralph char	*name;		/* program name */
44*12117Sralph char	*printer;	/* printer name */
45*12117Sralph char	host[32];	/* host machine name */
46*12117Sralph char	*from = host;	/* client's machine name */
47*12117Sralph 
48*12117Sralph /*
49*12117Sralph  * Create a connection to the remote printer server.
50*12117Sralph  * Most of this code comes from rcmd.c.
51*12117Sralph  */
52*12117Sralph getport()
53*12117Sralph {
54*12117Sralph 	struct hostent *hp;
55*12117Sralph 	struct servent *sp;
56*12117Sralph 	struct sockaddr_in sin;
57*12117Sralph 	int s, timo = 1, lport = IPPORT_RESERVED - 1;
58*12117Sralph 
59*12117Sralph 	/*
60*12117Sralph 	 * Get the host address and port number to connect to.
61*12117Sralph 	 */
62*12117Sralph 	if (RM == NULL)
63*12117Sralph 		fatal("no remote host to connect to");
64*12117Sralph 	hp = gethostbyname(RM);
65*12117Sralph 	if (hp == NULL)
66*12117Sralph 		fatal("unknown host %s", RM);
67*12117Sralph 	sp = getservbyname("printer", "tcp");
68*12117Sralph 	if (sp == NULL)
69*12117Sralph 		fatal("printer/tcp: unknown service");
70*12117Sralph 	bzero((char *)&sin, sizeof(sin));
71*12117Sralph 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
72*12117Sralph 	sin.sin_family = hp->h_addrtype;
73*12117Sralph 	sin.sin_port = sp->s_port;
74*12117Sralph 
75*12117Sralph 	/*
76*12117Sralph 	 * Try connecting to the server.
77*12117Sralph 	 */
78*12117Sralph retry:
79*12117Sralph 	s = rresvport(&lport);
80*12117Sralph 	if (s < 0)
81*12117Sralph 		return(-1);
82*12117Sralph 	if (connect(s, (caddr_t)&sin, sizeof(sin), 0) < 0) {
83*12117Sralph 		if (errno == EADDRINUSE) {
84*12117Sralph 			close(s);
85*12117Sralph 			lport--;
86*12117Sralph 			goto retry;
87*12117Sralph 		}
88*12117Sralph 		if (errno == ECONNREFUSED && timo <= 16) {
89*12117Sralph 			(void) close(s);
90*12117Sralph 			sleep(timo);
91*12117Sralph 			timo *= 2;
92*12117Sralph 			goto retry;
93*12117Sralph 		}
94*12117Sralph 		return(-1);
95*12117Sralph 	}
96*12117Sralph 	return(s);
97*12117Sralph }
98*12117Sralph 
99*12117Sralph rresvport(alport)
100*12117Sralph 	int *alport;
101*12117Sralph {
102*12117Sralph 	struct sockaddr_in sin;
103*12117Sralph 	int s;
104*12117Sralph 
105*12117Sralph 	sin.sin_family = AF_INET;
106*12117Sralph 	sin.sin_addr.s_addr = 0;
107*12117Sralph 	s = socket(AF_INET, SOCK_STREAM, 0);
108*12117Sralph 	if (s < 0)
109*12117Sralph 		return(-1);
110*12117Sralph 	for (;;) {
111*12117Sralph 		sin.sin_port = htons((u_short) *alport);
112*12117Sralph 		if (bind(s, (caddr_t)&sin, sizeof(sin), 0) >= 0)
113*12117Sralph 			return(s);
114*12117Sralph 		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL)
115*12117Sralph 			return(-1);
116*12117Sralph 		(*alport)--;
117*12117Sralph 		if (*alport == IPPORT_RESERVED/2) {
118*12117Sralph 			printf("%s: All ports in use\n", name);
119*12117Sralph 			return(-1);
120*12117Sralph 		}
121*12117Sralph 	}
122*12117Sralph }
123*12117Sralph 
124*12117Sralph /*
125*12117Sralph  * Getline reads a line from the control file cfp, removes tabs, converts
126*12117Sralph  *  new-line to null and leaves it in line.
127*12117Sralph  * Returns 0 at EOF or the number of characters read.
128*12117Sralph  */
129*12117Sralph getline(cfp)
130*12117Sralph 	FILE *cfp;
131*12117Sralph {
132*12117Sralph 	register int linel = 0;
133*12117Sralph 	register char *lp = line;
134*12117Sralph 	register c;
135*12117Sralph 
136*12117Sralph 	while ((c = getc(cfp)) != '\n') {
137*12117Sralph 		if (c == EOF)
138*12117Sralph 			return(0);
139*12117Sralph 		if (c == '\t') {
140*12117Sralph 			do {
141*12117Sralph 				*lp++ = ' ';
142*12117Sralph 				linel++;
143*12117Sralph 			} while ((linel & 07) != 0);
144*12117Sralph 			continue;
145*12117Sralph 		}
146*12117Sralph 		*lp++ = c;
147*12117Sralph 		linel++;
148*12117Sralph 	}
149*12117Sralph 	*lp++ = '\0';
150*12117Sralph 	return(linel);
151*12117Sralph }
152*12117Sralph 
153*12117Sralph /*
154*12117Sralph  * Scan the current directory and make a list of daemon files sorted by
155*12117Sralph  * creation time.
156*12117Sralph  * Return the number of entries and a pointer to the list.
157*12117Sralph  */
158*12117Sralph getq(namelist)
159*12117Sralph 	struct queue *(*namelist[]);
160*12117Sralph {
161*12117Sralph 	register struct direct *d;
162*12117Sralph 	register struct queue *q, **queue;
163*12117Sralph 	register int nitems;
164*12117Sralph 	struct stat stbuf;
165*12117Sralph 	int arraysz, compar();
166*12117Sralph 	DIR *dirp;
167*12117Sralph 
168*12117Sralph 	if ((dirp = opendir(".")) == NULL)
169*12117Sralph 		return(-1);
170*12117Sralph 	if (fstat(dirp->dd_fd, &stbuf) < 0)
171*12117Sralph 		return(-1);
172*12117Sralph 
173*12117Sralph 	/*
174*12117Sralph 	 * Estimate the array size by taking the size of the directory file
175*12117Sralph 	 * and dividing it by a multiple of the minimum size entry.
176*12117Sralph 	 */
177*12117Sralph 	arraysz = (stbuf.st_size / 24);
178*12117Sralph 	queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
179*12117Sralph 	if (queue == NULL)
180*12117Sralph 		return(-1);
181*12117Sralph 
182*12117Sralph 	nitems = 0;
183*12117Sralph 	while ((d = readdir(dirp)) != NULL) {
184*12117Sralph 		if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
185*12117Sralph 			continue;	/* daemon control files only */
186*12117Sralph 		if (stat(d->d_name, &stbuf) < 0)
187*12117Sralph 			continue;	/* Doesn't exist */
188*12117Sralph 		q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
189*12117Sralph 		if (q == NULL)
190*12117Sralph 			return(-1);
191*12117Sralph 		q->q_time = stbuf.st_mtime;
192*12117Sralph 		strcpy(q->q_name, d->d_name);
193*12117Sralph 		/*
194*12117Sralph 		 * Check to make sure the array has space left and
195*12117Sralph 		 * realloc the maximum size.
196*12117Sralph 		 */
197*12117Sralph 		if (++nitems > arraysz) {
198*12117Sralph 			queue = (struct queue **)realloc((char *)queue,
199*12117Sralph 				(stbuf.st_size/12) * sizeof(struct queue *));
200*12117Sralph 			if (queue == NULL)
201*12117Sralph 				return(-1);
202*12117Sralph 		}
203*12117Sralph 		queue[nitems-1] = q;
204*12117Sralph 	}
205*12117Sralph 	closedir(dirp);
206*12117Sralph 	if (nitems)
207*12117Sralph 		qsort(queue, nitems, sizeof(struct queue *), compar);
208*12117Sralph 	*namelist = queue;
209*12117Sralph 	return(nitems);
210*12117Sralph }
211*12117Sralph 
212*12117Sralph /*
213*12117Sralph  * Compare modification times.
214*12117Sralph  */
215*12117Sralph static
216*12117Sralph compar(p1, p2)
217*12117Sralph 	register struct queue **p1, **p2;
218*12117Sralph {
219*12117Sralph 	if ((*p1)->q_time < (*p2)->q_time)
220*12117Sralph 		return(-1);
221*12117Sralph 	if ((*p1)->q_time > (*p2)->q_time)
222*12117Sralph 		return(1);
223*12117Sralph 	return(0);
224*12117Sralph }
225*12117Sralph 
226*12117Sralph /*VARARGS1*/
227*12117Sralph status(msg, a1, a2, a3)
228*12117Sralph 	char *msg;
229*12117Sralph {
230*12117Sralph 	register int fd;
231*12117Sralph 	char buf[BUFSIZ];
232*12117Sralph 
233*12117Sralph 	umask(0);
234*12117Sralph 	if ((fd = open(ST, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK, 0664)) < 0)
235*12117Sralph 		fatal("cannot create status file");
236*12117Sralph 	sprintf(buf, msg, a1, a2, a3);
237*12117Sralph 	strcat(buf, "\n");
238*12117Sralph 	(void) write(fd, buf, strlen(buf));
239*12117Sralph 	(void) close(fd);
240*12117Sralph }
241*12117Sralph 
242*12117Sralph /*VARARGS1*/
243*12117Sralph fatal(msg, a1, a2, a3)
244*12117Sralph 	char *msg;
245*12117Sralph {
246*12117Sralph 	if (from != host)
247*12117Sralph 		printf("%s: ", host);
248*12117Sralph 	printf("%s: ", name);
249*12117Sralph 	if (printer)
250*12117Sralph 		printf("%s: ", printer);
251*12117Sralph 	printf(msg, a1, a2, a3);
252*12117Sralph 	putchar('\n');
253*12117Sralph 	exit(1);
254*12117Sralph }
255*12117Sralph 
256*12117Sralph fatalerror(msg)
257*12117Sralph 	char *msg;
258*12117Sralph {
259*12117Sralph 	extern int sys_nerr;
260*12117Sralph 	extern char *sys_errlist[];
261*12117Sralph 
262*12117Sralph 	printf("%s: ", name);
263*12117Sralph 	if (*msg)
264*12117Sralph 		printf("%s: ", msg);
265*12117Sralph 	fputs(errno < sys_nerr ? sys_errlist[errno] : "Unknown error" , stdout);
266*12117Sralph 	putchar('\n');
267*12117Sralph 	exit(1);
268*12117Sralph }
269