xref: /freebsd/contrib/libpcap/testprogs/selpolltest.c (revision 57e22627f9459b9dfd6043b32e02ecfcf205e176)
1*57e22627SCy Schubert /*
2*57e22627SCy Schubert  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
3*57e22627SCy Schubert  *	The Regents of the University of California.  All rights reserved.
4*57e22627SCy Schubert  *
5*57e22627SCy Schubert  * Redistribution and use in source and binary forms, with or without
6*57e22627SCy Schubert  * modification, are permitted provided that: (1) source code distributions
7*57e22627SCy Schubert  * retain the above copyright notice and this paragraph in its entirety, (2)
8*57e22627SCy Schubert  * distributions including binary code include the above copyright notice and
9*57e22627SCy Schubert  * this paragraph in its entirety in the documentation or other materials
10*57e22627SCy Schubert  * provided with the distribution, and (3) all advertising materials mentioning
11*57e22627SCy Schubert  * features or use of this software display the following acknowledgement:
12*57e22627SCy Schubert  * ``This product includes software developed by the University of California,
13*57e22627SCy Schubert  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*57e22627SCy Schubert  * the University nor the names of its contributors may be used to endorse
15*57e22627SCy Schubert  * or promote products derived from this software without specific prior
16*57e22627SCy Schubert  * written permission.
17*57e22627SCy Schubert  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*57e22627SCy Schubert  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*57e22627SCy Schubert  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*57e22627SCy Schubert  */
21*57e22627SCy Schubert 
22*57e22627SCy Schubert #include "varattrs.h"
23*57e22627SCy Schubert 
24*57e22627SCy Schubert #ifndef lint
25*57e22627SCy Schubert static const char copyright[] _U_ =
26*57e22627SCy Schubert     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
27*57e22627SCy Schubert The Regents of the University of California.  All rights reserved.\n";
28*57e22627SCy Schubert #endif
29*57e22627SCy Schubert 
30*57e22627SCy Schubert /*
31*57e22627SCy Schubert  * Tests how select() and poll() behave on the selectable file descriptor
32*57e22627SCy Schubert  * for a pcap_t.
33*57e22627SCy Schubert  *
34*57e22627SCy Schubert  * This would be significantly different on Windows, as it'd test
35*57e22627SCy Schubert  * how WaitForMultipleObjects() would work on the event handle for a
36*57e22627SCy Schubert  * pcap_t.
37*57e22627SCy Schubert  */
38*57e22627SCy Schubert #include <pcap.h>
39*57e22627SCy Schubert #include <stdio.h>
40*57e22627SCy Schubert #include <stdlib.h>
41*57e22627SCy Schubert #include <string.h>
42*57e22627SCy Schubert #include <stdarg.h>
43*57e22627SCy Schubert #include <unistd.h>
44*57e22627SCy Schubert #include <errno.h>
45*57e22627SCy Schubert #include <sys/types.h>
46*57e22627SCy Schubert #ifdef HAVE_SYS_SELECT_H
47*57e22627SCy Schubert #include <sys/select.h>
48*57e22627SCy Schubert #else
49*57e22627SCy Schubert #include <sys/time.h>	/* older UN*Xes */
50*57e22627SCy Schubert #endif
51*57e22627SCy Schubert #include <poll.h>
52*57e22627SCy Schubert 
53*57e22627SCy Schubert #include "pcap/funcattrs.h"
54*57e22627SCy Schubert 
55*57e22627SCy Schubert static char *program_name;
56*57e22627SCy Schubert 
57*57e22627SCy Schubert /* Forwards */
58*57e22627SCy Schubert static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
59*57e22627SCy Schubert static void PCAP_NORETURN usage(void);
60*57e22627SCy Schubert static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
61*57e22627SCy Schubert static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
62*57e22627SCy Schubert static char *copy_argv(char **);
63*57e22627SCy Schubert 
64*57e22627SCy Schubert static pcap_t *pd;
65*57e22627SCy Schubert 
66*57e22627SCy Schubert int
67*57e22627SCy Schubert main(int argc, char **argv)
68*57e22627SCy Schubert {
69*57e22627SCy Schubert 	register int op;
70*57e22627SCy Schubert 	bpf_u_int32 localnet, netmask;
71*57e22627SCy Schubert 	register char *cp, *cmdbuf, *device;
72*57e22627SCy Schubert 	int doselect, dopoll, dotimeout, dononblock;
73*57e22627SCy Schubert 	const char *mechanism;
74*57e22627SCy Schubert 	struct bpf_program fcode;
75*57e22627SCy Schubert 	char ebuf[PCAP_ERRBUF_SIZE];
76*57e22627SCy Schubert 	pcap_if_t *devlist;
77*57e22627SCy Schubert 	int selectable_fd;
78*57e22627SCy Schubert 	struct timeval *required_timeout;
79*57e22627SCy Schubert 	int status;
80*57e22627SCy Schubert 	int packet_count;
81*57e22627SCy Schubert 
82*57e22627SCy Schubert 	device = NULL;
83*57e22627SCy Schubert 	doselect = 0;
84*57e22627SCy Schubert 	dopoll = 0;
85*57e22627SCy Schubert 	mechanism = NULL;
86*57e22627SCy Schubert 	dotimeout = 0;
87*57e22627SCy Schubert 	dononblock = 0;
88*57e22627SCy Schubert 	if ((cp = strrchr(argv[0], '/')) != NULL)
89*57e22627SCy Schubert 		program_name = cp + 1;
90*57e22627SCy Schubert 	else
91*57e22627SCy Schubert 		program_name = argv[0];
92*57e22627SCy Schubert 
93*57e22627SCy Schubert 	opterr = 0;
94*57e22627SCy Schubert 	while ((op = getopt(argc, argv, "i:sptn")) != -1) {
95*57e22627SCy Schubert 		switch (op) {
96*57e22627SCy Schubert 
97*57e22627SCy Schubert 		case 'i':
98*57e22627SCy Schubert 			device = optarg;
99*57e22627SCy Schubert 			break;
100*57e22627SCy Schubert 
101*57e22627SCy Schubert 		case 's':
102*57e22627SCy Schubert 			doselect = 1;
103*57e22627SCy Schubert 			mechanism = "select() and pcap_dispatch()";
104*57e22627SCy Schubert 			break;
105*57e22627SCy Schubert 
106*57e22627SCy Schubert 		case 'p':
107*57e22627SCy Schubert 			dopoll = 1;
108*57e22627SCy Schubert 			mechanism = "poll() and pcap_dispatch()";
109*57e22627SCy Schubert 			break;
110*57e22627SCy Schubert 
111*57e22627SCy Schubert 		case 't':
112*57e22627SCy Schubert 			dotimeout = 1;
113*57e22627SCy Schubert 			break;
114*57e22627SCy Schubert 
115*57e22627SCy Schubert 		case 'n':
116*57e22627SCy Schubert 			dononblock = 1;
117*57e22627SCy Schubert 			break;
118*57e22627SCy Schubert 
119*57e22627SCy Schubert 		default:
120*57e22627SCy Schubert 			usage();
121*57e22627SCy Schubert 			/* NOTREACHED */
122*57e22627SCy Schubert 		}
123*57e22627SCy Schubert 	}
124*57e22627SCy Schubert 
125*57e22627SCy Schubert 	if (doselect && dopoll) {
126*57e22627SCy Schubert 		fprintf(stderr, "selpolltest: choose select (-s) or poll (-p), but not both\n");
127*57e22627SCy Schubert 		return 1;
128*57e22627SCy Schubert 	}
129*57e22627SCy Schubert 	if (dotimeout && !doselect && !dopoll) {
130*57e22627SCy Schubert 		fprintf(stderr, "selpolltest: timeout (-t) requires select (-s) or poll (-p)\n");
131*57e22627SCy Schubert 		return 1;
132*57e22627SCy Schubert 	}
133*57e22627SCy Schubert 	if (device == NULL) {
134*57e22627SCy Schubert 		if (pcap_findalldevs(&devlist, ebuf) == -1)
135*57e22627SCy Schubert 			error("%s", ebuf);
136*57e22627SCy Schubert 		if (devlist == NULL)
137*57e22627SCy Schubert 			error("no interfaces available for capture");
138*57e22627SCy Schubert 		device = strdup(devlist->name);
139*57e22627SCy Schubert 		pcap_freealldevs(devlist);
140*57e22627SCy Schubert 	}
141*57e22627SCy Schubert 	*ebuf = '\0';
142*57e22627SCy Schubert 	pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
143*57e22627SCy Schubert 	if (pd == NULL)
144*57e22627SCy Schubert 		error("%s", ebuf);
145*57e22627SCy Schubert 	else if (*ebuf)
146*57e22627SCy Schubert 		warning("%s", ebuf);
147*57e22627SCy Schubert 	if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
148*57e22627SCy Schubert 		localnet = 0;
149*57e22627SCy Schubert 		netmask = 0;
150*57e22627SCy Schubert 		warning("%s", ebuf);
151*57e22627SCy Schubert 	}
152*57e22627SCy Schubert 	cmdbuf = copy_argv(&argv[optind]);
153*57e22627SCy Schubert 
154*57e22627SCy Schubert 	if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
155*57e22627SCy Schubert 		error("%s", pcap_geterr(pd));
156*57e22627SCy Schubert 	if (pcap_setfilter(pd, &fcode) < 0)
157*57e22627SCy Schubert 		error("%s", pcap_geterr(pd));
158*57e22627SCy Schubert 
159*57e22627SCy Schubert 	if (doselect || dopoll) {
160*57e22627SCy Schubert 		/*
161*57e22627SCy Schubert 		 * We need either an FD on which to do select()/poll()
162*57e22627SCy Schubert 		 * or, if there isn't one, a timeout to use in select()/
163*57e22627SCy Schubert 		 * poll().
164*57e22627SCy Schubert 		 */
165*57e22627SCy Schubert 		selectable_fd = pcap_get_selectable_fd(pd);
166*57e22627SCy Schubert 		if (selectable_fd == -1) {
167*57e22627SCy Schubert 			printf("Listening on %s, using %s, with a timeout\n",
168*57e22627SCy Schubert 			    device, mechanism);
169*57e22627SCy Schubert 			required_timeout = pcap_get_required_select_timeout(pd);
170*57e22627SCy Schubert 			if (required_timeout == NULL)
171*57e22627SCy Schubert 				error("select()/poll() isn't supported on %s, even with a timeout",
172*57e22627SCy Schubert 				    device);
173*57e22627SCy Schubert 
174*57e22627SCy Schubert 			/*
175*57e22627SCy Schubert 			 * As we won't be notified by select() or poll()
176*57e22627SCy Schubert 			 * that a read can be done, we'll have to periodically
177*57e22627SCy Schubert 			 * try reading from the device every time the required
178*57e22627SCy Schubert 			 * timeout expires, and we don't want those attempts
179*57e22627SCy Schubert 			 * to block if nothing has arrived in that interval,
180*57e22627SCy Schubert 			 * so we want to force non-blocking mode.
181*57e22627SCy Schubert 			 */
182*57e22627SCy Schubert 			dononblock = 1;
183*57e22627SCy Schubert 		} else {
184*57e22627SCy Schubert 			printf("Listening on %s, using %s\n", device,
185*57e22627SCy Schubert 			    mechanism);
186*57e22627SCy Schubert 			required_timeout = NULL;
187*57e22627SCy Schubert 		}
188*57e22627SCy Schubert 	} else
189*57e22627SCy Schubert 		printf("Listening on %s, using pcap_dispatch()\n", device);
190*57e22627SCy Schubert 
191*57e22627SCy Schubert 	if (dononblock) {
192*57e22627SCy Schubert 		if (pcap_setnonblock(pd, 1, ebuf) == -1)
193*57e22627SCy Schubert 			error("pcap_setnonblock failed: %s", ebuf);
194*57e22627SCy Schubert 	}
195*57e22627SCy Schubert 	if (doselect) {
196*57e22627SCy Schubert 		for (;;) {
197*57e22627SCy Schubert 			fd_set setread, setexcept;
198*57e22627SCy Schubert 			struct timeval seltimeout;
199*57e22627SCy Schubert 
200*57e22627SCy Schubert 			FD_ZERO(&setread);
201*57e22627SCy Schubert 			if (selectable_fd != -1) {
202*57e22627SCy Schubert 				FD_SET(selectable_fd, &setread);
203*57e22627SCy Schubert 				FD_ZERO(&setexcept);
204*57e22627SCy Schubert 				FD_SET(selectable_fd, &setexcept);
205*57e22627SCy Schubert 			}
206*57e22627SCy Schubert 			if (dotimeout) {
207*57e22627SCy Schubert 				seltimeout.tv_sec = 0;
208*57e22627SCy Schubert 				if (required_timeout != NULL &&
209*57e22627SCy Schubert 				    required_timeout->tv_usec < 1000)
210*57e22627SCy Schubert 					seltimeout.tv_usec = required_timeout->tv_usec;
211*57e22627SCy Schubert 				else
212*57e22627SCy Schubert 					seltimeout.tv_usec = 1000;
213*57e22627SCy Schubert 				status = select(selectable_fd + 1, &setread,
214*57e22627SCy Schubert 				    NULL, &setexcept, &seltimeout);
215*57e22627SCy Schubert 			} else if (required_timeout != NULL) {
216*57e22627SCy Schubert 				seltimeout = *required_timeout;
217*57e22627SCy Schubert 				status = select(selectable_fd + 1, &setread,
218*57e22627SCy Schubert 				    NULL, &setexcept, &seltimeout);
219*57e22627SCy Schubert 			} else {
220*57e22627SCy Schubert 				status = select((selectable_fd == -1) ?
221*57e22627SCy Schubert 				    0 : selectable_fd + 1, &setread,
222*57e22627SCy Schubert 				    NULL, &setexcept, NULL);
223*57e22627SCy Schubert 			}
224*57e22627SCy Schubert 			if (status == -1) {
225*57e22627SCy Schubert 				printf("Select returns error (%s)\n",
226*57e22627SCy Schubert 				    strerror(errno));
227*57e22627SCy Schubert 			} else {
228*57e22627SCy Schubert 				if (selectable_fd == -1) {
229*57e22627SCy Schubert 					if (status != 0)
230*57e22627SCy Schubert 						printf("Select returned a descriptor\n");
231*57e22627SCy Schubert 				} else {
232*57e22627SCy Schubert 					if (status == 0)
233*57e22627SCy Schubert 						printf("Select timed out: ");
234*57e22627SCy Schubert 					else
235*57e22627SCy Schubert 						printf("Select returned a descriptor: ");
236*57e22627SCy Schubert 					if (FD_ISSET(selectable_fd, &setread))
237*57e22627SCy Schubert 						printf("readable, ");
238*57e22627SCy Schubert 					else
239*57e22627SCy Schubert 						printf("not readable, ");
240*57e22627SCy Schubert 					if (FD_ISSET(selectable_fd, &setexcept))
241*57e22627SCy Schubert 						printf("exceptional condition\n");
242*57e22627SCy Schubert 					else
243*57e22627SCy Schubert 						printf("no exceptional condition\n");
244*57e22627SCy Schubert 				}
245*57e22627SCy Schubert 				packet_count = 0;
246*57e22627SCy Schubert 				status = pcap_dispatch(pd, -1, countme,
247*57e22627SCy Schubert 				    (u_char *)&packet_count);
248*57e22627SCy Schubert 				if (status < 0)
249*57e22627SCy Schubert 					break;
250*57e22627SCy Schubert 				/*
251*57e22627SCy Schubert 				 * Don't report this if we're using a
252*57e22627SCy Schubert 				 * required timeout and we got no packets,
253*57e22627SCy Schubert 				 * because that could be a very short timeout,
254*57e22627SCy Schubert 				 * and we don't want to spam the user with
255*57e22627SCy Schubert 				 * a ton of "no packets" reports.
256*57e22627SCy Schubert 				 */
257*57e22627SCy Schubert 				if (status != 0 || packet_count != 0 ||
258*57e22627SCy Schubert 				    required_timeout != NULL) {
259*57e22627SCy Schubert 					printf("%d packets seen, %d packets counted after select returns\n",
260*57e22627SCy Schubert 					    status, packet_count);
261*57e22627SCy Schubert 				}
262*57e22627SCy Schubert 			}
263*57e22627SCy Schubert 		}
264*57e22627SCy Schubert 	} else if (dopoll) {
265*57e22627SCy Schubert 		for (;;) {
266*57e22627SCy Schubert 			struct pollfd fd;
267*57e22627SCy Schubert 			int polltimeout;
268*57e22627SCy Schubert 
269*57e22627SCy Schubert 			fd.fd = selectable_fd;
270*57e22627SCy Schubert 			fd.events = POLLIN;
271*57e22627SCy Schubert 			if (dotimeout)
272*57e22627SCy Schubert 				polltimeout = 1;
273*57e22627SCy Schubert 			else if (required_timeout != NULL &&
274*57e22627SCy Schubert 			    required_timeout->tv_usec >= 1000)
275*57e22627SCy Schubert 				polltimeout = required_timeout->tv_usec/1000;
276*57e22627SCy Schubert 			else
277*57e22627SCy Schubert 				polltimeout = -1;
278*57e22627SCy Schubert 			status = poll(&fd, (selectable_fd == -1) ? 0 : 1, polltimeout);
279*57e22627SCy Schubert 			if (status == -1) {
280*57e22627SCy Schubert 				printf("Poll returns error (%s)\n",
281*57e22627SCy Schubert 				    strerror(errno));
282*57e22627SCy Schubert 			} else {
283*57e22627SCy Schubert 				if (selectable_fd == -1) {
284*57e22627SCy Schubert 					if (status != 0)
285*57e22627SCy Schubert 						printf("Poll returned a descriptor\n");
286*57e22627SCy Schubert 				} else {
287*57e22627SCy Schubert 					if (status == 0)
288*57e22627SCy Schubert 						printf("Poll timed out\n");
289*57e22627SCy Schubert 					else {
290*57e22627SCy Schubert 						printf("Poll returned a descriptor: ");
291*57e22627SCy Schubert 						if (fd.revents & POLLIN)
292*57e22627SCy Schubert 							printf("readable, ");
293*57e22627SCy Schubert 						else
294*57e22627SCy Schubert 							printf("not readable, ");
295*57e22627SCy Schubert 						if (fd.revents & POLLERR)
296*57e22627SCy Schubert 							printf("exceptional condition, ");
297*57e22627SCy Schubert 						else
298*57e22627SCy Schubert 							printf("no exceptional condition, ");
299*57e22627SCy Schubert 						if (fd.revents & POLLHUP)
300*57e22627SCy Schubert 							printf("disconnect, ");
301*57e22627SCy Schubert 						else
302*57e22627SCy Schubert 							printf("no disconnect, ");
303*57e22627SCy Schubert 						if (fd.revents & POLLNVAL)
304*57e22627SCy Schubert 							printf("invalid\n");
305*57e22627SCy Schubert 						else
306*57e22627SCy Schubert 							printf("not invalid\n");
307*57e22627SCy Schubert 					}
308*57e22627SCy Schubert 				}
309*57e22627SCy Schubert 				packet_count = 0;
310*57e22627SCy Schubert 				status = pcap_dispatch(pd, -1, countme,
311*57e22627SCy Schubert 				    (u_char *)&packet_count);
312*57e22627SCy Schubert 				if (status < 0)
313*57e22627SCy Schubert 					break;
314*57e22627SCy Schubert 				/*
315*57e22627SCy Schubert 				 * Don't report this if we're using a
316*57e22627SCy Schubert 				 * required timeout and we got no packets,
317*57e22627SCy Schubert 				 * because that could be a very short timeout,
318*57e22627SCy Schubert 				 * and we don't want to spam the user with
319*57e22627SCy Schubert 				 * a ton of "no packets" reports.
320*57e22627SCy Schubert 				 */
321*57e22627SCy Schubert 				if (status != 0 || packet_count != 0 ||
322*57e22627SCy Schubert 				    required_timeout != NULL) {
323*57e22627SCy Schubert 					printf("%d packets seen, %d packets counted after poll returns\n",
324*57e22627SCy Schubert 					    status, packet_count);
325*57e22627SCy Schubert 				}
326*57e22627SCy Schubert 			}
327*57e22627SCy Schubert 		}
328*57e22627SCy Schubert 	} else {
329*57e22627SCy Schubert 		for (;;) {
330*57e22627SCy Schubert 			packet_count = 0;
331*57e22627SCy Schubert 			status = pcap_dispatch(pd, -1, countme,
332*57e22627SCy Schubert 			    (u_char *)&packet_count);
333*57e22627SCy Schubert 			if (status < 0)
334*57e22627SCy Schubert 				break;
335*57e22627SCy Schubert 			printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
336*57e22627SCy Schubert 			    status, packet_count);
337*57e22627SCy Schubert 		}
338*57e22627SCy Schubert 	}
339*57e22627SCy Schubert 	if (status == -2) {
340*57e22627SCy Schubert 		/*
341*57e22627SCy Schubert 		 * We got interrupted, so perhaps we didn't
342*57e22627SCy Schubert 		 * manage to finish a line we were printing.
343*57e22627SCy Schubert 		 * Print an extra newline, just in case.
344*57e22627SCy Schubert 		 */
345*57e22627SCy Schubert 		putchar('\n');
346*57e22627SCy Schubert 	}
347*57e22627SCy Schubert 	(void)fflush(stdout);
348*57e22627SCy Schubert 	if (status == -1) {
349*57e22627SCy Schubert 		/*
350*57e22627SCy Schubert 		 * Error.  Report it.
351*57e22627SCy Schubert 		 */
352*57e22627SCy Schubert 		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
353*57e22627SCy Schubert 		    program_name, pcap_geterr(pd));
354*57e22627SCy Schubert 	}
355*57e22627SCy Schubert 	pcap_close(pd);
356*57e22627SCy Schubert 	exit(status == -1 ? 1 : 0);
357*57e22627SCy Schubert }
358*57e22627SCy Schubert 
359*57e22627SCy Schubert static void
360*57e22627SCy Schubert countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
361*57e22627SCy Schubert {
362*57e22627SCy Schubert 	int *counterp = (int *)user;
363*57e22627SCy Schubert 
364*57e22627SCy Schubert 	(*counterp)++;
365*57e22627SCy Schubert }
366*57e22627SCy Schubert 
367*57e22627SCy Schubert static void
368*57e22627SCy Schubert usage(void)
369*57e22627SCy Schubert {
370*57e22627SCy Schubert 	(void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
371*57e22627SCy Schubert 	    program_name);
372*57e22627SCy Schubert 	exit(1);
373*57e22627SCy Schubert }
374*57e22627SCy Schubert 
375*57e22627SCy Schubert /* VARARGS */
376*57e22627SCy Schubert static void
377*57e22627SCy Schubert error(const char *fmt, ...)
378*57e22627SCy Schubert {
379*57e22627SCy Schubert 	va_list ap;
380*57e22627SCy Schubert 
381*57e22627SCy Schubert 	(void)fprintf(stderr, "%s: ", program_name);
382*57e22627SCy Schubert 	va_start(ap, fmt);
383*57e22627SCy Schubert 	(void)vfprintf(stderr, fmt, ap);
384*57e22627SCy Schubert 	va_end(ap);
385*57e22627SCy Schubert 	if (*fmt) {
386*57e22627SCy Schubert 		fmt += strlen(fmt);
387*57e22627SCy Schubert 		if (fmt[-1] != '\n')
388*57e22627SCy Schubert 			(void)fputc('\n', stderr);
389*57e22627SCy Schubert 	}
390*57e22627SCy Schubert 	exit(1);
391*57e22627SCy Schubert 	/* NOTREACHED */
392*57e22627SCy Schubert }
393*57e22627SCy Schubert 
394*57e22627SCy Schubert /* VARARGS */
395*57e22627SCy Schubert static void
396*57e22627SCy Schubert warning(const char *fmt, ...)
397*57e22627SCy Schubert {
398*57e22627SCy Schubert 	va_list ap;
399*57e22627SCy Schubert 
400*57e22627SCy Schubert 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
401*57e22627SCy Schubert 	va_start(ap, fmt);
402*57e22627SCy Schubert 	(void)vfprintf(stderr, fmt, ap);
403*57e22627SCy Schubert 	va_end(ap);
404*57e22627SCy Schubert 	if (*fmt) {
405*57e22627SCy Schubert 		fmt += strlen(fmt);
406*57e22627SCy Schubert 		if (fmt[-1] != '\n')
407*57e22627SCy Schubert 			(void)fputc('\n', stderr);
408*57e22627SCy Schubert 	}
409*57e22627SCy Schubert }
410*57e22627SCy Schubert 
411*57e22627SCy Schubert /*
412*57e22627SCy Schubert  * Copy arg vector into a new buffer, concatenating arguments with spaces.
413*57e22627SCy Schubert  */
414*57e22627SCy Schubert static char *
415*57e22627SCy Schubert copy_argv(register char **argv)
416*57e22627SCy Schubert {
417*57e22627SCy Schubert 	register char **p;
418*57e22627SCy Schubert 	register u_int len = 0;
419*57e22627SCy Schubert 	char *buf;
420*57e22627SCy Schubert 	char *src, *dst;
421*57e22627SCy Schubert 
422*57e22627SCy Schubert 	p = argv;
423*57e22627SCy Schubert 	if (*p == 0)
424*57e22627SCy Schubert 		return 0;
425*57e22627SCy Schubert 
426*57e22627SCy Schubert 	while (*p)
427*57e22627SCy Schubert 		len += strlen(*p++) + 1;
428*57e22627SCy Schubert 
429*57e22627SCy Schubert 	buf = (char *)malloc(len);
430*57e22627SCy Schubert 	if (buf == NULL)
431*57e22627SCy Schubert 		error("copy_argv: malloc");
432*57e22627SCy Schubert 
433*57e22627SCy Schubert 	p = argv;
434*57e22627SCy Schubert 	dst = buf;
435*57e22627SCy Schubert 	while ((src = *p++) != NULL) {
436*57e22627SCy Schubert 		while ((*dst++ = *src++) != '\0')
437*57e22627SCy Schubert 			;
438*57e22627SCy Schubert 		dst[-1] = ' ';
439*57e22627SCy Schubert 	}
440*57e22627SCy Schubert 	dst[-1] = '\0';
441*57e22627SCy Schubert 
442*57e22627SCy Schubert 	return buf;
443*57e22627SCy Schubert }
444