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