GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/lpr/lprm/../common_source/common.c Lines: 0 202 0.0 %
Date: 2017-11-07 Branches: 0 127 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: common.c,v 1.41 2016/02/29 17:26:01 jca Exp $	*/
2
/*	$NetBSD: common.c,v 1.21 2000/08/09 14:28:50 itojun Exp $	*/
3
4
/*
5
 * Copyright (c) 1983, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 * (c) UNIX System Laboratories, Inc.
8
 * All or some portions of this file are derived from material licensed
9
 * to the University of California by American Telephone and Telegraph
10
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11
 * the permission of UNIX System Laboratories, Inc.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions
15
 * are met:
16
 * 1. Redistributions of source code must retain the above copyright
17
 *    notice, this list of conditions and the following disclaimer.
18
 * 2. Redistributions in binary form must reproduce the above copyright
19
 *    notice, this list of conditions and the following disclaimer in the
20
 *    documentation and/or other materials provided with the distribution.
21
 * 3. Neither the name of the University nor the names of its contributors
22
 *    may be used to endorse or promote products derived from this software
23
 *    without specific prior written permission.
24
 *
25
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
 * SUCH DAMAGE.
36
 */
37
38
#include <sys/stat.h>
39
#include <sys/time.h>
40
41
#include <sys/socket.h>
42
#include <netinet/in.h>
43
#include <arpa/inet.h>
44
#include <netdb.h>
45
46
#include <dirent.h>
47
#include <errno.h>
48
#include <fcntl.h>
49
#include <unistd.h>
50
#include <limits.h>
51
#include <stdlib.h>
52
#include <stdio.h>
53
#include <string.h>
54
#include <signal.h>
55
#include <stdarg.h>
56
#include <ifaddrs.h>
57
#include "lp.h"
58
#include "pathnames.h"
59
60
/*
61
 * Routines and data common to all the line printer functions.
62
 */
63
64
char	*AF;		/* accounting file */
65
long	 BR;		/* baud rate if lp is a tty */
66
char	*CF;		/* name of cifplot filter (per job) */
67
char	*DF;		/* name of tex filter (per job) */
68
long	 DU;		/* daemon user-id */
69
char	*FF;		/* form feed string */
70
char	*GF;		/* name of graph(1G) filter (per job) */
71
long	 HL;		/* print header last */
72
char	*IF;		/* name of input filter (created per job) */
73
char	*LF;		/* log file for error messages */
74
char	*LO;		/* lock file name */
75
char	*LP;		/* line printer device name */
76
long	 MC;		/* maximum number of copies allowed */
77
char	*MS;		/* stty flags to set if lp is a tty */
78
long	 MX;		/* maximum number of blocks to copy */
79
char	*NF;		/* name of ditroff filter (per job) */
80
char	*OF;		/* name of output filter (created once) */
81
long	 PL;		/* page length */
82
long	 PW;		/* page width */
83
long	 PX;		/* page width in pixels */
84
long	 PY;		/* page length in pixels */
85
char	*RF;		/* name of fortran text filter (per job) */
86
char    *RG;		/* restricted group */
87
char	*RM;		/* remote machine name */
88
char	*RP;		/* remote printer name */
89
long	 RS;		/* restricted to those with local accounts */
90
long	 RW;		/* open LP for reading and writing */
91
long	 SB;		/* short banner instead of normal header */
92
long	 SC;		/* suppress multiple copies */
93
char	*SD;		/* spool directory */
94
long	 SF;		/* suppress FF on each print job */
95
long	 SH;		/* suppress header page */
96
char	*ST;		/* status file name */
97
char	*TF;		/* name of troff filter (per job) */
98
char	*TR;		/* trailer string to be output when Q empties */
99
char	*VF;		/* name of vplot filter (per job) */
100
101
char	line[BUFSIZ];
102
int	remote;		/* true if sending files to a remote host */
103
104
static int compar(const void *, const void *);
105
106
/*
107
 * Create a TCP connection to host "rhost" at port "rport".
108
 * If rport == 0, then use the printer service port.
109
 * Most of this code comes from rcmd.c.
110
 */
111
int
112
getport(char *rhost, int rport)
113
{
114
	struct addrinfo hints, *res, *r;
115
	u_int timo = 1;
116
	int s, lport = IPPORT_RESERVED - 1;
117
	int error;
118
	int refuse, trial;
119
	char pbuf[NI_MAXSERV];
120
121
	/*
122
	 * Get the host address and port number to connect to.
123
	 */
124
	if (rhost == NULL)
125
		fatal("no remote host to connect to");
126
	memset(&hints, 0, sizeof(hints));
127
	hints.ai_family = PF_UNSPEC;
128
	hints.ai_socktype = SOCK_STREAM;
129
	if (rport)
130
		snprintf(pbuf, sizeof(pbuf), "%d", rport);
131
	else
132
		snprintf(pbuf, sizeof(pbuf), "printer");
133
	siginterrupt(SIGINT, 1);
134
	error = getaddrinfo(rhost, pbuf, &hints, &res);
135
	siginterrupt(SIGINT, 0);
136
	if (error)
137
		fatal("printer/tcp: %s", gai_strerror(error));
138
139
	/*
140
	 * Try connecting to the server.
141
	 */
142
retry:
143
	s = -1;
144
	refuse = trial = 0;
145
	for (r = res; r; r = r->ai_next) {
146
		trial++;
147
retryport:
148
		PRIV_START;
149
		s = rresvport_af(&lport, r->ai_family);
150
		PRIV_END;
151
		if (s < 0) {
152
			/* fall back to non-privileged port */
153
			if (errno != EACCES ||
154
			    (s = socket(r->ai_family, SOCK_STREAM, 0)) < 0) {
155
				freeaddrinfo(res);
156
				return(-1);
157
			}
158
		}
159
		siginterrupt(SIGINT, 1);
160
		if (connect(s, r->ai_addr, r->ai_addrlen) < 0) {
161
			error = errno;
162
			siginterrupt(SIGINT, 0);
163
			(void)close(s);
164
			s = -1;
165
			errno = error;
166
			if (errno == EADDRINUSE) {
167
				lport--;
168
				goto retryport;
169
			} else if (errno == ECONNREFUSED)
170
				refuse++;
171
			continue;
172
		} else {
173
			siginterrupt(SIGINT, 0);
174
			break;
175
		}
176
	}
177
	if (s < 0 && trial == refuse && timo <= 16) {
178
		sleep(timo);
179
		timo *= 2;
180
		goto retry;
181
	}
182
	if (res)
183
		freeaddrinfo(res);
184
185
	/* Don't worry if we get an error from setsockopt(). */
186
	trial = 1;
187
	setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &trial, sizeof(trial));
188
189
	return(s);
190
}
191
192
/*
193
 * Getline reads a line from the control file cfp, removes tabs, converts
194
 *  new-line to null and leaves it in line.
195
 * Returns 0 at EOF or the number of characters read.
196
 */
197
int
198
get_line(FILE *cfp)
199
{
200
	int linel = 0;
201
	char *lp = line;
202
	int c;
203
204
	while ((c = getc(cfp)) != '\n' && linel+1<sizeof(line)) {
205
		if (c == EOF)
206
			return(0);
207
		if (c == '\t') {
208
			do {
209
				*lp++ = ' ';
210
				linel++;
211
			} while ((linel & 07) != 0 && linel+1 < sizeof(line));
212
			continue;
213
		}
214
		*lp++ = c;
215
		linel++;
216
	}
217
	*lp++ = '\0';
218
	return(linel);
219
}
220
221
/*
222
 * Scan the current directory and make a list of daemon files sorted by
223
 * creation time.
224
 * Return the number of entries and a pointer to the list.
225
 */
226
int
227
getq(struct queue ***namelist)
228
{
229
	struct dirent *d;
230
	struct queue *q, **queue = NULL;
231
	size_t nitems = 0, arraysz;
232
	struct stat stbuf;
233
	DIR *dirp;
234
235
	PRIV_START;
236
	dirp = opendir(SD);
237
	PRIV_END;
238
	if (dirp == NULL)
239
		return(-1);
240
	if (fstat(dirfd(dirp), &stbuf) < 0)
241
		goto errdone;
242
243
	/*
244
	 * Estimate the array size by taking the size of the directory file
245
	 * and dividing it by a multiple of the minimum size entry.
246
	 */
247
	arraysz = (stbuf.st_size / 24);
248
	queue = calloc(arraysz, sizeof(struct queue *));
249
	if (queue == NULL)
250
		goto errdone;
251
252
	while ((d = readdir(dirp)) != NULL) {
253
		if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
254
			continue;	/* daemon control files only */
255
		PRIV_START;
256
		if (stat(d->d_name, &stbuf) < 0) {
257
			PRIV_END;
258
			continue;	/* Doesn't exist */
259
		}
260
		PRIV_END;
261
		q = malloc(sizeof(struct queue));
262
		if (q == NULL)
263
			goto errdone;
264
		q->q_time = stbuf.st_mtime;
265
		strlcpy(q->q_name, d->d_name, sizeof(q->q_name));
266
267
		/*
268
		 * Check to make sure the array has space left and
269
		 * realloc the maximum size.
270
		 */
271
		if (nitems == arraysz) {
272
			struct queue **newqueue;
273
			newqueue = reallocarray(queue,
274
			    arraysz, 2 * sizeof(struct queue *));
275
			if (newqueue == NULL) {
276
				free(q);
277
				goto errdone;
278
			}
279
			arraysz *= 2;
280
			queue = newqueue;
281
		}
282
		queue[nitems++] = q;
283
	}
284
	closedir(dirp);
285
	if (nitems)
286
		qsort(queue, nitems, sizeof(struct queue *), compar);
287
	*namelist = queue;
288
	return(nitems);
289
290
errdone:
291
	if (queue != NULL) {
292
		while (nitems--)
293
			free(queue[nitems]);
294
		free(queue);
295
	}
296
	closedir(dirp);
297
	return(-1);
298
}
299
300
/*
301
 * Compare modification times.
302
 */
303
static int
304
compar(const void *v1, const void *v2)
305
{
306
	struct queue *p1 = *(struct queue **)v1;
307
	struct queue *p2 = *(struct queue **)v2;
308
309
	return(p1->q_time - p2->q_time);
310
}
311
312
/*
313
 * Figure out whether the local machine is the same
314
 * as the remote machine (RM) entry (if it exists).
315
 */
316
char *
317
checkremote(void)
318
{
319
	char lname[NI_MAXHOST], rname[NI_MAXHOST];
320
	struct addrinfo hints, *res, *res0;
321
	static char errbuf[128];
322
	int error;
323
	struct ifaddrs *ifap, *ifa;
324
	const int niflags = NI_NUMERICHOST;
325
#ifdef __KAME__
326
	struct sockaddr_in6 sin6;
327
	struct sockaddr_in6 *sin6p;
328
#endif
329
330
	remote = 0;	/* assume printer is local on failure */
331
332
	if (RM == NULL || *RM == '\0')
333
		return NULL;
334
335
	/* get the local interface addresses */
336
	siginterrupt(SIGINT, 1);
337
	if (getifaddrs(&ifap) < 0) {
338
		(void)snprintf(errbuf, sizeof(errbuf),
339
		    "unable to get local interface address: %s",
340
		    strerror(errno));
341
		siginterrupt(SIGINT, 0);
342
		return errbuf;
343
	}
344
	siginterrupt(SIGINT, 0);
345
346
	/* get the remote host addresses (RM) */
347
	memset(&hints, 0, sizeof(hints));
348
	hints.ai_flags = AI_CANONNAME;
349
	hints.ai_family = PF_UNSPEC;
350
	hints.ai_socktype = SOCK_STREAM;
351
	res = NULL;
352
	siginterrupt(SIGINT, 1);
353
	error = getaddrinfo(RM, NULL, &hints, &res0);
354
	siginterrupt(SIGINT, 0);
355
	if (error) {
356
		(void)snprintf(errbuf, sizeof(errbuf),
357
		    "unable to resolve remote machine %s: %s",
358
		    RM, gai_strerror(error));
359
		freeifaddrs(ifap);
360
		return errbuf;
361
	}
362
363
	remote = 1;	/* assume printer is remote */
364
365
	for (res = res0; res; res = res->ai_next) {
366
		siginterrupt(SIGINT, 1);
367
		error = getnameinfo(res->ai_addr, res->ai_addrlen,
368
		    rname, sizeof(rname), NULL, 0, niflags);
369
		siginterrupt(SIGINT, 0);
370
		if (error != 0)
371
			continue;
372
		for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
373
#ifdef __KAME__
374
			sin6p = (struct sockaddr_in6 *)ifa->ifa_addr;
375
			if (ifa->ifa_addr->sa_family == AF_INET6 &&
376
			    ifa->ifa_addr->sa_len == sizeof(sin6) &&
377
			    IN6_IS_ADDR_LINKLOCAL(&sin6p->sin6_addr) &&
378
			    *(u_int16_t *)&sin6p->sin6_addr.s6_addr[2]) {
379
				/* kame scopeid hack */
380
				memcpy(&sin6, ifa->ifa_addr, sizeof(sin6));
381
				sin6.sin6_scope_id =
382
				    ntohs(*(u_int16_t *)&sin6p->sin6_addr.s6_addr[2]);
383
				sin6.sin6_addr.s6_addr[2] = 0;
384
				sin6.sin6_addr.s6_addr[3] = 0;
385
				siginterrupt(SIGINT, 1);
386
				error = getnameinfo((struct sockaddr *)&sin6,
387
				    sin6.sin6_len, lname, sizeof(lname),
388
				    NULL, 0, niflags);
389
				siginterrupt(SIGINT, 0);
390
				if (error != 0)
391
					continue;
392
			} else
393
#endif
394
			siginterrupt(SIGINT, 1);
395
			error = getnameinfo(ifa->ifa_addr,
396
			    ifa->ifa_addr->sa_len, lname, sizeof(lname), NULL,
397
			    0, niflags);
398
			siginterrupt(SIGINT, 0);
399
			if (error != 0)
400
				continue;
401
402
			if (strcmp(rname, lname) == 0) {
403
				remote = 0;
404
				goto done;
405
			}
406
		}
407
	}
408
done:
409
	freeaddrinfo(res0);
410
	freeifaddrs(ifap);
411
	return NULL;
412
}
413
414
__dead void
415
fatal(const char *msg, ...)
416
{
417
	extern char *__progname;
418
	va_list ap;
419
420
	va_start(ap, msg);
421
	if (from != host)
422
		(void)printf("%s: ", host);
423
	(void)printf("%s: ", __progname);
424
	if (printer)
425
		(void)printf("%s: ", printer);
426
	(void)vprintf(msg, ap);
427
	va_end(ap);
428
	(void)putchar('\n');
429
	exit(1);
430
}
431
432
int
433
safe_open(const char *path, int flags, mode_t mode)
434
{
435
	int fd, serrno;
436
	struct stat stbuf;
437
438
	if ((fd = open(path, flags|O_NONBLOCK, mode)) < 0 ||
439
	    fstat(fd, &stbuf) < 0) {
440
		if (fd >= 0) {
441
			serrno = errno;
442
			close(fd);
443
			errno = serrno;
444
		}
445
		return (-1);
446
	}
447
	if (!S_ISREG(stbuf.st_mode)) {
448
		close(fd);
449
		errno = EACCES;
450
		return (-1);
451
	}
452
	if (mode)
453
		(void)fchmod(fd, mode);
454
	return (fd);
455
}
456
457
/*
458
 * Make sure there's some work to do before forking off a child - lpd
459
 * Check to see if anything in queue - lpq
460
 */
461
int
462
ckqueue(char *cap)
463
{
464
	struct dirent *d;
465
	DIR *dirp;
466
	char *spooldir;
467
468
	if (cgetstr(cap, "sd", &spooldir) >= 0) {
469
		dirp = opendir(spooldir);
470
		free(spooldir);
471
	} else
472
		dirp = opendir(_PATH_DEFSPOOL);
473
474
	if (dirp == NULL)
475
		return (-1);
476
	while ((d = readdir(dirp)) != NULL) {
477
		if (d->d_name[0] == 'c' && d->d_name[1] == 'f') {
478
			closedir(dirp);
479
			return (1);		/* found a cf file */
480
		}
481
	}
482
	closedir(dirp);
483
	return (0);
484
}