xref: /freebsd/usr.sbin/lpr/common_source/common.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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 /*
41 static char sccsid[] = "@(#)common.c	8.5 (Berkeley) 4/28/95";
42 */
43 static const char rcsid[] =
44   "$FreeBSD$";
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  */
64 char	line[BUFSIZ];
65 char	*name;		/* program name */
66 
67 extern uid_t	uid, euid;
68 
69 static 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  */
76 int
77 getline(cfp)
78 	FILE *cfp;
79 {
80 	register int linel = 0;
81 	register char *lp = line;
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  */
106 int
107 getq(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 
166 errdone:
167 	closedir(dirp);
168 	return(-1);
169 }
170 
171 /*
172  * Compare modification times.
173  */
174 static int
175 compar(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 */
186 void
187 delay(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 
200 char *
201 lock_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 
222 char *
223 status_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 
250 void
251 #ifdef __STDC__
252 fatal(const struct printer *pp, const char *msg, ...)
253 #else
254 fatal(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  */
284 void
285 closeallfds(start)
286 	int start;
287 {
288 	int stop = getdtablesize();
289 	for (; start < stop; start++)
290 		close(start);
291 }
292 
293