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