common.c revision 1.8 1 /* $NetBSD: common.c,v 1.8 1995/11/28 19:43:19 jtc Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41 #ifndef lint
42 static char sccsid[] = "@(#)common.c 8.2 (Berkeley) 1/21/94";
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/stat.h>
47
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <netdb.h>
51
52 #include <dirent.h>
53 #include <errno.h>
54 #include <unistd.h>
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include "lp.h"
59 #include "pathnames.h"
60
61 /*
62 * Routines and data common to all the line printer functions.
63 */
64
65 char *AF; /* accounting file */
66 long BR; /* baud rate if lp is a tty */
67 char *CF; /* name of cifplot filter (per job) */
68 char *DF; /* name of tex filter (per job) */
69 long DU; /* daeomon user-id */
70 long FC; /* flags to clear if lp is a tty */
71 char *FF; /* form feed string */
72 long FS; /* flags to set if lp is a tty */
73 char *GF; /* name of graph(1G) filter (per job) */
74 long HL; /* print header last */
75 char *IF; /* name of input filter (created per job) */
76 char *LF; /* log file for error messages */
77 char *LO; /* lock file name */
78 char *LP; /* line printer device name */
79 long MC; /* maximum number of copies allowed */
80 char *MS; /* stty flags to set if lp is a tty */
81 long MX; /* maximum number of blocks to copy */
82 char *NF; /* name of ditroff filter (per job) */
83 char *OF; /* name of output filter (created once) */
84 char *PF; /* name of vrast filter (per job) */
85 long PL; /* page length */
86 long PW; /* page width */
87 long PX; /* page width in pixels */
88 long PY; /* page length in pixels */
89 char *RF; /* name of fortran text filter (per job) */
90 char *RG; /* resricted group */
91 char *RM; /* remote machine name */
92 char *RP; /* remote printer name */
93 long RS; /* restricted to those with local accounts */
94 long RW; /* open LP for reading and writing */
95 long SB; /* short banner instead of normal header */
96 long SC; /* suppress multiple copies */
97 char *SD; /* spool directory */
98 long SF; /* suppress FF on each print job */
99 long SH; /* suppress header page */
100 char *ST; /* status file name */
101 char *TF; /* name of troff filter (per job) */
102 char *TR; /* trailer string to be output when Q empties */
103 char *VF; /* name of vplot filter (per job) */
104 long XC; /* flags to clear for local mode */
105 long XS; /* flags to set for local mode */
106
107 char line[BUFSIZ];
108 char *bp; /* pointer into printcap buffer. */
109 char *name; /* program name */
110 char *printer; /* printer name */
111 /* host machine name */
112 char host[MAXHOSTNAMELEN];
113 char *from = host; /* client's machine name */
114 int sendtorem; /* are we sending to a remote? */
115 char *printcapdb[2] = { _PATH_PRINTCAP, 0 };
116
117 extern uid_t uid, euid;
118
119 static int compar __P((const void *, const void *));
120
121 /*
122 * Create a connection to the remote printer server.
123 * Most of this code comes from rcmd.c.
124 */
125 int
126 getport(rhost)
127 char *rhost;
128 {
129 struct hostent *hp;
130 struct servent *sp;
131 struct sockaddr_in sin;
132 int s, timo = 1, lport = IPPORT_RESERVED - 1;
133 int err;
134
135 /*
136 * Get the host address and port number to connect to.
137 */
138 if (rhost == NULL)
139 fatal("no remote host to connect to");
140 hp = gethostbyname(rhost);
141 if (hp == NULL)
142 fatal("unknown host %s", rhost);
143 sp = getservbyname("printer", "tcp");
144 if (sp == NULL)
145 fatal("printer/tcp: unknown service");
146 bzero((char *)&sin, sizeof(sin));
147 bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
148 sin.sin_family = hp->h_addrtype;
149 sin.sin_port = sp->s_port;
150
151 /*
152 * Try connecting to the server.
153 */
154 retry:
155 seteuid(euid);
156 s = rresvport(&lport);
157 seteuid(uid);
158 if (s < 0)
159 return(-1);
160 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
161 err = errno;
162 (void) close(s);
163 errno = err;
164 if (errno == EADDRINUSE) {
165 lport--;
166 goto retry;
167 }
168 if (errno == ECONNREFUSED && timo <= 16) {
169 sleep(timo);
170 timo *= 2;
171 goto retry;
172 }
173 return(-1);
174 }
175 return(s);
176 }
177
178 /*
179 * Getline reads a line from the control file cfp, removes tabs, converts
180 * new-line to null and leaves it in line.
181 * Returns 0 at EOF or the number of characters read.
182 */
183 int
184 getline(cfp)
185 FILE *cfp;
186 {
187 register int linel = 0;
188 register char *lp = line;
189 register c;
190
191 while ((c = getc(cfp)) != '\n') {
192 if (c == EOF)
193 return(0);
194 if (c == '\t') {
195 do {
196 *lp++ = ' ';
197 linel++;
198 } while ((linel & 07) != 0);
199 continue;
200 }
201 *lp++ = c;
202 linel++;
203 }
204 *lp++ = '\0';
205 return(linel);
206 }
207
208 /*
209 * Scan the current directory and make a list of daemon files sorted by
210 * creation time.
211 * Return the number of entries and a pointer to the list.
212 */
213 int
214 getq(namelist)
215 struct queue *(*namelist[]);
216 {
217 register struct dirent *d;
218 register struct queue *q, **queue;
219 register int nitems;
220 struct stat stbuf;
221 DIR *dirp;
222 int arraysz;
223
224 seteuid(euid);
225 if ((dirp = opendir(SD)) == NULL)
226 return(-1);
227 if (fstat(dirp->dd_fd, &stbuf) < 0)
228 goto errdone;
229 seteuid(uid);
230
231 /*
232 * Estimate the array size by taking the size of the directory file
233 * and dividing it by a multiple of the minimum size entry.
234 */
235 arraysz = (stbuf.st_size / 24);
236 queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
237 if (queue == NULL)
238 goto errdone;
239
240 nitems = 0;
241 while ((d = readdir(dirp)) != NULL) {
242 if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
243 continue; /* daemon control files only */
244 seteuid(euid);
245 if (stat(d->d_name, &stbuf) < 0)
246 continue; /* Doesn't exist */
247 seteuid(uid);
248 q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
249 if (q == NULL)
250 goto errdone;
251 q->q_time = stbuf.st_mtime;
252 strcpy(q->q_name, d->d_name);
253 /*
254 * Check to make sure the array has space left and
255 * realloc the maximum size.
256 */
257 if (++nitems > arraysz) {
258 queue = (struct queue **)realloc((char *)queue,
259 (stbuf.st_size/12) * sizeof(struct queue *));
260 if (queue == NULL)
261 goto errdone;
262 }
263 queue[nitems-1] = q;
264 }
265 closedir(dirp);
266 if (nitems)
267 qsort(queue, nitems, sizeof(struct queue *), compar);
268 *namelist = queue;
269 return(nitems);
270
271 errdone:
272 closedir(dirp);
273 return(-1);
274 }
275
276 /*
277 * Compare modification times.
278 */
279 static int
280 compar(p1, p2)
281 const void *p1, *p2;
282 {
283 if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time)
284 return(-1);
285 if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time)
286 return(1);
287 return(0);
288 }
289
290 /*
291 * Figure out whether the local machine is the same
292 * as the remote machine (RM) entry (if it exists).
293 */
294 char *
295 checkremote()
296 {
297 char name[MAXHOSTNAMELEN];
298 register struct hostent *hp;
299 static char errbuf[128];
300
301 sendtorem = 0; /* assume printer is local */
302 if (RM != (char *)NULL) {
303 /* get the official name of the local host */
304 gethostname(name, sizeof(name));
305 name[sizeof(name)-1] = '\0';
306 hp = gethostbyname(name);
307 if (hp == (struct hostent *) NULL) {
308 (void) snprintf(errbuf, sizeof(errbuf),
309 "unable to get official name for local machine %s",
310 name);
311 return errbuf;
312 } else (void) strcpy(name, hp->h_name);
313
314 /* get the official name of RM */
315 hp = gethostbyname(RM);
316 if (hp == (struct hostent *) NULL) {
317 (void) snprintf(errbuf, sizeof(errbuf),
318 "unable to get official name for remote machine %s",
319 RM);
320 return errbuf;
321 }
322
323 /*
324 * if the two hosts are not the same,
325 * then the printer must be remote.
326 */
327 if (strcmp(name, hp->h_name) != 0)
328 sendtorem = 1;
329 }
330 return (char *)0;
331 }
332
333 #if __STDC__
334 #include <stdarg.h>
335 #else
336 #include <varargs.h>
337 #endif
338
339 void
340 #if __STDC__
341 fatal(const char *msg, ...)
342 #else
343 fatal(msg, va_alist)
344 char *msg;
345 va_dcl
346 #endif
347 {
348 va_list ap;
349 #if __STDC__
350 va_start(ap, msg);
351 #else
352 va_start(ap);
353 #endif
354 if (from != host)
355 (void)printf("%s: ", host);
356 (void)printf("%s: ", name);
357 if (printer)
358 (void)printf("%s: ", printer);
359 (void)vprintf(msg, ap);
360 va_end(ap);
361 (void)putchar('\n');
362 exit(1);
363 }
364