1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)common.c	5.5 (Berkeley) 08/22/89";
20 #endif /* not lint */
21 
22 /*
23  * Routines and data common to all the line printer functions.
24  */
25 
26 #include "lp.h"
27 
28 int	DU;		/* daeomon user-id */
29 int	MX;		/* maximum number of blocks to copy */
30 int	MC;		/* maximum number of copies allowed */
31 char	*LP;		/* line printer device name */
32 char	*RM;		/* remote machine name */
33 char	*RP;		/* remote printer name */
34 char	*LO;		/* lock file name */
35 char	*ST;		/* status file name */
36 char	*SD;		/* spool directory */
37 char	*AF;		/* accounting file */
38 char	*LF;		/* log file for error messages */
39 char	*OF;		/* name of output filter (created once) */
40 char	*IF;		/* name of input filter (created per job) */
41 char	*RF;		/* name of fortran text filter (per job) */
42 char	*TF;		/* name of troff filter (per job) */
43 char	*NF;		/* name of ditroff filter (per job) */
44 char	*DF;		/* name of tex filter (per job) */
45 char	*GF;		/* name of graph(1G) filter (per job) */
46 char	*VF;		/* name of vplot filter (per job) */
47 char	*CF;		/* name of cifplot filter (per job) */
48 char	*PF;		/* name of vrast filter (per job) */
49 char	*FF;		/* form feed string */
50 char	*TR;		/* trailer string to be output when Q empties */
51 short	SC;		/* suppress multiple copies */
52 short	SF;		/* suppress FF on each print job */
53 short	SH;		/* suppress header page */
54 short	SB;		/* short banner instead of normal header */
55 short	HL;		/* print header last */
56 short	RW;		/* open LP for reading and writing */
57 short	PW;		/* page width */
58 short	PL;		/* page length */
59 short	PX;		/* page width in pixels */
60 short	PY;		/* page length in pixels */
61 short	BR;		/* baud rate if lp is a tty */
62 int	FC;		/* flags to clear if lp is a tty */
63 int	FS;		/* flags to set if lp is a tty */
64 int	XC;		/* flags to clear for local mode */
65 int	XS;		/* flags to set for local mode */
66 short	RS;		/* restricted to those with local accounts */
67 
68 char	line[BUFSIZ];
69 char	pbuf[BUFSIZ/2];	/* buffer for printcap strings */
70 char	*bp = pbuf;	/* pointer into pbuf for pgetent() */
71 char	*name;		/* program name */
72 char	*printer;	/* printer name */
73 char	host[32];	/* host machine name */
74 char	*from = host;	/* client's machine name */
75 int	sendtorem;	/* are we sending to a remote? */
76 
77 /*
78  * Create a connection to the remote printer server.
79  * Most of this code comes from rcmd.c.
80  */
81 getport(rhost)
82 	char *rhost;
83 {
84 	struct hostent *hp;
85 	struct servent *sp;
86 	struct sockaddr_in sin;
87 	int s, timo = 1, lport = IPPORT_RESERVED - 1;
88 	int err;
89 
90 	/*
91 	 * Get the host address and port number to connect to.
92 	 */
93 	if (rhost == NULL)
94 		fatal("no remote host to connect to");
95 	hp = gethostbyname(rhost);
96 	if (hp == NULL)
97 		fatal("unknown host %s", rhost);
98 	sp = getservbyname("printer", "tcp");
99 	if (sp == NULL)
100 		fatal("printer/tcp: unknown service");
101 	bzero((char *)&sin, sizeof(sin));
102 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
103 	sin.sin_family = hp->h_addrtype;
104 	sin.sin_port = sp->s_port;
105 
106 	/*
107 	 * Try connecting to the server.
108 	 */
109 retry:
110 	s = rresvport(&lport);
111 	if (s < 0)
112 		return(-1);
113 	if (connect(s, (caddr_t)&sin, sizeof(sin)) < 0) {
114 		err = errno;
115 		(void) close(s);
116 		errno = err;
117 		if (errno == EADDRINUSE) {
118 			lport--;
119 			goto retry;
120 		}
121 		if (errno == ECONNREFUSED && timo <= 16) {
122 			sleep(timo);
123 			timo *= 2;
124 			goto retry;
125 		}
126 		return(-1);
127 	}
128 	return(s);
129 }
130 
131 /*
132  * Getline reads a line from the control file cfp, removes tabs, converts
133  *  new-line to null and leaves it in line.
134  * Returns 0 at EOF or the number of characters read.
135  */
136 getline(cfp)
137 	FILE *cfp;
138 {
139 	register int linel = 0;
140 	register char *lp = line;
141 	register c;
142 
143 	while ((c = getc(cfp)) != '\n') {
144 		if (c == EOF)
145 			return(0);
146 		if (c == '\t') {
147 			do {
148 				*lp++ = ' ';
149 				linel++;
150 			} while ((linel & 07) != 0);
151 			continue;
152 		}
153 		*lp++ = c;
154 		linel++;
155 	}
156 	*lp++ = '\0';
157 	return(linel);
158 }
159 
160 /*
161  * Scan the current directory and make a list of daemon files sorted by
162  * creation time.
163  * Return the number of entries and a pointer to the list.
164  */
165 getq(namelist)
166 	struct queue *(*namelist[]);
167 {
168 	register struct direct *d;
169 	register struct queue *q, **queue;
170 	register int nitems;
171 	struct stat stbuf;
172 	int arraysz, compar();
173 	DIR *dirp;
174 
175 	if ((dirp = opendir(SD)) == NULL)
176 		return(-1);
177 	if (fstat(dirp->dd_fd, &stbuf) < 0)
178 		goto errdone;
179 
180 	/*
181 	 * Estimate the array size by taking the size of the directory file
182 	 * and dividing it by a multiple of the minimum size entry.
183 	 */
184 	arraysz = (stbuf.st_size / 24);
185 	queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
186 	if (queue == NULL)
187 		goto errdone;
188 
189 	nitems = 0;
190 	while ((d = readdir(dirp)) != NULL) {
191 		if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
192 			continue;	/* daemon control files only */
193 		if (stat(d->d_name, &stbuf) < 0)
194 			continue;	/* Doesn't exist */
195 		q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
196 		if (q == NULL)
197 			goto errdone;
198 		q->q_time = stbuf.st_mtime;
199 		strcpy(q->q_name, d->d_name);
200 		/*
201 		 * Check to make sure the array has space left and
202 		 * realloc the maximum size.
203 		 */
204 		if (++nitems > arraysz) {
205 			queue = (struct queue **)realloc((char *)queue,
206 				(stbuf.st_size/12) * sizeof(struct queue *));
207 			if (queue == NULL)
208 				goto errdone;
209 		}
210 		queue[nitems-1] = q;
211 	}
212 	closedir(dirp);
213 	if (nitems)
214 		qsort(queue, nitems, sizeof(struct queue *), compar);
215 	*namelist = queue;
216 	return(nitems);
217 
218 errdone:
219 	closedir(dirp);
220 	return(-1);
221 }
222 
223 /*
224  * Compare modification times.
225  */
226 static
227 compar(p1, p2)
228 	register struct queue **p1, **p2;
229 {
230 	if ((*p1)->q_time < (*p2)->q_time)
231 		return(-1);
232 	if ((*p1)->q_time > (*p2)->q_time)
233 		return(1);
234 	return(0);
235 }
236 
237 /*
238  * Figure out whether the local machine is the same
239  * as the remote machine (RM) entry (if it exists).
240  */
241 char *
242 checkremote()
243 {
244 	char name[MAXHOSTNAMELEN];
245 	register struct hostent *hp;
246 	static char errbuf[128];
247 
248 	sendtorem = 0;	/* assume printer is local */
249 	if (RM != (char *)NULL) {
250 		/* get the official name of the local host */
251 		gethostname(name, sizeof(name));
252 		name[sizeof(name)-1] = '\0';
253 		hp = gethostbyname(name);
254 		if (hp == (struct hostent *) NULL) {
255 		    (void) sprintf(errbuf,
256 			"unable to get official name for local machine %s",
257 			name);
258 		    return errbuf;
259 		} else (void) strcpy(name, hp->h_name);
260 
261 		/* get the official name of RM */
262 		hp = gethostbyname(RM);
263 		if (hp == (struct hostent *) NULL) {
264 		    (void) sprintf(errbuf,
265 			"unable to get official name for remote machine %s",
266 			RM);
267 		    return errbuf;
268 		}
269 
270 		/*
271 		 * if the two hosts are not the same,
272 		 * then the printer must be remote.
273 		 */
274 		if (strcmp(name, hp->h_name) != 0)
275 			sendtorem = 1;
276 	}
277 	return (char *)0;
278 }
279 
280 /*VARARGS1*/
281 fatal(msg, a1, a2, a3)
282 	char *msg;
283 {
284 	if (from != host)
285 		printf("%s: ", host);
286 	printf("%s: ", name);
287 	if (printer)
288 		printf("%s: ", printer);
289 	printf(msg, a1, a2, a3);
290 	putchar('\n');
291 	exit(1);
292 }
293