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