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