Deleted Added
full compact
common.c (31492) common.c (39084)
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. 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/*
41static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95";
42*/
43static const char rcsid[] =
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. 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/*
41static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95";
42*/
43static const char rcsid[] =
44 "$Id$";
44 "$Id: common.c,v 1.10 1997/12/02 20:45:18 wollman Exp $";
45#endif /* not lint */
46
47#include <sys/param.h>
48#include <sys/stat.h>
49#include <sys/time.h>
50
51#include <dirent.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56
57#include "lp.h"
58#include "lp.local.h"
59#include "pathnames.h"
60
61/*
62 * Routines and data common to all the line printer functions.
63 */
64char line[BUFSIZ];
65char *name; /* program name */
66
67extern uid_t uid, euid;
68
69static int compar __P((const void *, const void *));
70
71/*
72 * Getline reads a line from the control file cfp, removes tabs, converts
73 * new-line to null and leaves it in line.
74 * Returns 0 at EOF or the number of characters read.
75 */
76int
77getline(cfp)
78 FILE *cfp;
79{
80 register int linel = 0;
81 register char *lp = line;
45#endif /* not lint */
46
47#include <sys/param.h>
48#include <sys/stat.h>
49#include <sys/time.h>
50
51#include <dirent.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56
57#include "lp.h"
58#include "lp.local.h"
59#include "pathnames.h"
60
61/*
62 * Routines and data common to all the line printer functions.
63 */
64char line[BUFSIZ];
65char *name; /* program name */
66
67extern uid_t uid, euid;
68
69static int compar __P((const void *, const void *));
70
71/*
72 * Getline reads a line from the control file cfp, removes tabs, converts
73 * new-line to null and leaves it in line.
74 * Returns 0 at EOF or the number of characters read.
75 */
76int
77getline(cfp)
78 FILE *cfp;
79{
80 register int linel = 0;
81 register char *lp = line;
82 register c;
82 register int c;
83
84 while ((c = getc(cfp)) != '\n' && linel+1 < sizeof(line)) {
85 if (c == EOF)
86 return(0);
87 if (c == '\t') {
88 do {
89 *lp++ = ' ';
90 linel++;
91 } while ((linel & 07) != 0 && linel+1 < sizeof(line));
92 continue;
93 }
94 *lp++ = c;
95 linel++;
96 }
97 *lp++ = '\0';
98 return(linel);
99}
100
101/*
102 * Scan the current directory and make a list of daemon files sorted by
103 * creation time.
104 * Return the number of entries and a pointer to the list.
105 */
106int
107getq(pp, namelist)
108 const struct printer *pp;
109 struct queue *(*namelist[]);
110{
111 register struct dirent *d;
112 register struct queue *q, **queue;
113 register int nitems;
114 struct stat stbuf;
115 DIR *dirp;
116 int arraysz;
117
118 seteuid(euid);
119 if ((dirp = opendir(pp->spool_dir)) == NULL)
120 return(-1);
121 if (fstat(dirp->dd_fd, &stbuf) < 0)
122 goto errdone;
123 seteuid(uid);
124
125 /*
126 * Estimate the array size by taking the size of the directory file
127 * and dividing it by a multiple of the minimum size entry.
128 */
129 arraysz = (stbuf.st_size / 24);
130 queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
131 if (queue == NULL)
132 goto errdone;
133
134 nitems = 0;
135 while ((d = readdir(dirp)) != NULL) {
136 if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
137 continue; /* daemon control files only */
138 seteuid(euid);
139 if (stat(d->d_name, &stbuf) < 0)
140 continue; /* Doesn't exist */
141 seteuid(uid);
142 q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
143 if (q == NULL)
144 goto errdone;
145 q->q_time = stbuf.st_mtime;
146 strcpy(q->q_name, d->d_name);
147 /*
148 * Check to make sure the array has space left and
149 * realloc the maximum size.
150 */
151 if (++nitems > arraysz) {
152 arraysz *= 2;
153 queue = (struct queue **)realloc((char *)queue,
154 arraysz * sizeof(struct queue *));
155 if (queue == NULL)
156 goto errdone;
157 }
158 queue[nitems-1] = q;
159 }
160 closedir(dirp);
161 if (nitems)
162 qsort(queue, nitems, sizeof(struct queue *), compar);
163 *namelist = queue;
164 return(nitems);
165
166errdone:
167 closedir(dirp);
168 return(-1);
169}
170
171/*
172 * Compare modification times.
173 */
174static int
175compar(p1, p2)
176 const void *p1, *p2;
177{
178 if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time)
179 return(-1);
180 if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time)
181 return(1);
182 return(0);
183}
184
185/* sleep n milliseconds */
186void
187delay(n)
188 int n;
189{
190 struct timeval tdelay;
191
192 if (n <= 0 || n > 10000)
193 fatal((struct printer *)0, /* fatal() knows how to deal */
194 "unreasonable delay period (%d)", n);
195 tdelay.tv_sec = n / 1000;
196 tdelay.tv_usec = n * 1000 % 1000000;
197 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay);
198}
199
200char *
201lock_file_name(pp, buf, len)
202 const struct printer *pp;
203 char *buf;
204 size_t len;
205{
206 static char staticbuf[MAXPATHLEN];
207
208 if (buf == 0)
209 buf = staticbuf;
210 if (len == 0)
211 len = MAXPATHLEN;
212
213 if (pp->lock_file[0] == '/') {
214 buf[0] = '\0';
215 strncpy(buf, pp->lock_file, len);
216 } else {
217 snprintf(buf, len, "%s/%s", pp->spool_dir, pp->lock_file);
218 }
219 return buf;
220}
221
222char *
223status_file_name(pp, buf, len)
224 const struct printer *pp;
225 char *buf;
226 size_t len;
227{
228 static char staticbuf[MAXPATHLEN];
229
230 if (buf == 0)
231 buf = staticbuf;
232 if (len == 0)
233 len = MAXPATHLEN;
234
235 if (pp->status_file[0] == '/') {
236 buf[0] = '\0';
237 strncpy(buf, pp->status_file, len);
238 } else {
239 snprintf(buf, len, "%s/%s", pp->spool_dir, pp->status_file);
240 }
241 return buf;
242}
243
244#ifdef __STDC__
245#include <stdarg.h>
246#else
247#include <varargs.h>
248#endif
249
250void
251#ifdef __STDC__
252fatal(const struct printer *pp, const char *msg, ...)
253#else
254fatal(pp, msg, va_alist)
255 const struct printer *pp;
256 char *msg;
257 va_dcl
258#endif
259{
260 va_list ap;
261#ifdef __STDC__
262 va_start(ap, msg);
263#else
264 va_start(ap);
265#endif
266 if (from != host)
267 (void)printf("%s: ", host);
268 (void)printf("%s: ", name);
269 if (pp && pp->printer)
270 (void)printf("%s: ", pp->printer);
271 (void)vprintf(msg, ap);
272 va_end(ap);
273 (void)putchar('\n');
274 exit(1);
275}
276
277/*
278 * Close all file descriptors from START on up.
279 * This is a horrific kluge, since getdtablesize() might return
280 * ``infinity'', in which case we will be spending a long time
281 * closing ``files'' which were never open. Perhaps it would
282 * be better to close the first N fds, for some small value of N.
283 */
284void
285closeallfds(start)
286 int start;
287{
288 int stop = getdtablesize();
289 for (; start < stop; start++)
290 close(start);
291}
292
83
84 while ((c = getc(cfp)) != '\n' && linel+1 < sizeof(line)) {
85 if (c == EOF)
86 return(0);
87 if (c == '\t') {
88 do {
89 *lp++ = ' ';
90 linel++;
91 } while ((linel & 07) != 0 && linel+1 < sizeof(line));
92 continue;
93 }
94 *lp++ = c;
95 linel++;
96 }
97 *lp++ = '\0';
98 return(linel);
99}
100
101/*
102 * Scan the current directory and make a list of daemon files sorted by
103 * creation time.
104 * Return the number of entries and a pointer to the list.
105 */
106int
107getq(pp, namelist)
108 const struct printer *pp;
109 struct queue *(*namelist[]);
110{
111 register struct dirent *d;
112 register struct queue *q, **queue;
113 register int nitems;
114 struct stat stbuf;
115 DIR *dirp;
116 int arraysz;
117
118 seteuid(euid);
119 if ((dirp = opendir(pp->spool_dir)) == NULL)
120 return(-1);
121 if (fstat(dirp->dd_fd, &stbuf) < 0)
122 goto errdone;
123 seteuid(uid);
124
125 /*
126 * Estimate the array size by taking the size of the directory file
127 * and dividing it by a multiple of the minimum size entry.
128 */
129 arraysz = (stbuf.st_size / 24);
130 queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
131 if (queue == NULL)
132 goto errdone;
133
134 nitems = 0;
135 while ((d = readdir(dirp)) != NULL) {
136 if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
137 continue; /* daemon control files only */
138 seteuid(euid);
139 if (stat(d->d_name, &stbuf) < 0)
140 continue; /* Doesn't exist */
141 seteuid(uid);
142 q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
143 if (q == NULL)
144 goto errdone;
145 q->q_time = stbuf.st_mtime;
146 strcpy(q->q_name, d->d_name);
147 /*
148 * Check to make sure the array has space left and
149 * realloc the maximum size.
150 */
151 if (++nitems > arraysz) {
152 arraysz *= 2;
153 queue = (struct queue **)realloc((char *)queue,
154 arraysz * sizeof(struct queue *));
155 if (queue == NULL)
156 goto errdone;
157 }
158 queue[nitems-1] = q;
159 }
160 closedir(dirp);
161 if (nitems)
162 qsort(queue, nitems, sizeof(struct queue *), compar);
163 *namelist = queue;
164 return(nitems);
165
166errdone:
167 closedir(dirp);
168 return(-1);
169}
170
171/*
172 * Compare modification times.
173 */
174static int
175compar(p1, p2)
176 const void *p1, *p2;
177{
178 if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time)
179 return(-1);
180 if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time)
181 return(1);
182 return(0);
183}
184
185/* sleep n milliseconds */
186void
187delay(n)
188 int n;
189{
190 struct timeval tdelay;
191
192 if (n <= 0 || n > 10000)
193 fatal((struct printer *)0, /* fatal() knows how to deal */
194 "unreasonable delay period (%d)", n);
195 tdelay.tv_sec = n / 1000;
196 tdelay.tv_usec = n * 1000 % 1000000;
197 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay);
198}
199
200char *
201lock_file_name(pp, buf, len)
202 const struct printer *pp;
203 char *buf;
204 size_t len;
205{
206 static char staticbuf[MAXPATHLEN];
207
208 if (buf == 0)
209 buf = staticbuf;
210 if (len == 0)
211 len = MAXPATHLEN;
212
213 if (pp->lock_file[0] == '/') {
214 buf[0] = '\0';
215 strncpy(buf, pp->lock_file, len);
216 } else {
217 snprintf(buf, len, "%s/%s", pp->spool_dir, pp->lock_file);
218 }
219 return buf;
220}
221
222char *
223status_file_name(pp, buf, len)
224 const struct printer *pp;
225 char *buf;
226 size_t len;
227{
228 static char staticbuf[MAXPATHLEN];
229
230 if (buf == 0)
231 buf = staticbuf;
232 if (len == 0)
233 len = MAXPATHLEN;
234
235 if (pp->status_file[0] == '/') {
236 buf[0] = '\0';
237 strncpy(buf, pp->status_file, len);
238 } else {
239 snprintf(buf, len, "%s/%s", pp->spool_dir, pp->status_file);
240 }
241 return buf;
242}
243
244#ifdef __STDC__
245#include <stdarg.h>
246#else
247#include <varargs.h>
248#endif
249
250void
251#ifdef __STDC__
252fatal(const struct printer *pp, const char *msg, ...)
253#else
254fatal(pp, msg, va_alist)
255 const struct printer *pp;
256 char *msg;
257 va_dcl
258#endif
259{
260 va_list ap;
261#ifdef __STDC__
262 va_start(ap, msg);
263#else
264 va_start(ap);
265#endif
266 if (from != host)
267 (void)printf("%s: ", host);
268 (void)printf("%s: ", name);
269 if (pp && pp->printer)
270 (void)printf("%s: ", pp->printer);
271 (void)vprintf(msg, ap);
272 va_end(ap);
273 (void)putchar('\n');
274 exit(1);
275}
276
277/*
278 * Close all file descriptors from START on up.
279 * This is a horrific kluge, since getdtablesize() might return
280 * ``infinity'', in which case we will be spending a long time
281 * closing ``files'' which were never open. Perhaps it would
282 * be better to close the first N fds, for some small value of N.
283 */
284void
285closeallfds(start)
286 int start;
287{
288 int stop = getdtablesize();
289 for (; start < stop; start++)
290 close(start);
291}
292