xref: /netbsd-src/usr.bin/netstat/if.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: if.c,v 1.57 2003/11/15 11:54:34 ragge Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1988, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "from: @(#)if.c	8.2 (Berkeley) 2/21/94";
36 #else
37 __RCSID("$NetBSD: if.c,v 1.57 2003/11/15 11:54:34 ragge Exp $");
38 #endif
39 #endif /* not lint */
40 
41 #include <sys/types.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/time.h>
45 
46 #include <net/if.h>
47 #include <net/if_dl.h>
48 #include <net/if_types.h>
49 #include <netinet/in.h>
50 #include <netinet/in_var.h>
51 #include <netns/ns.h>
52 #include <netns/ns_if.h>
53 #include <netiso/iso.h>
54 #include <netiso/iso_var.h>
55 #include <arpa/inet.h>
56 
57 #include <signal.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <unistd.h>
62 #include <netdb.h>
63 
64 #include "netstat.h"
65 
66 #define	YES	1
67 #define	NO	0
68 
69 static void sidewaysintpr __P((u_int, u_long));
70 static void catchalarm __P((int));
71 
72 /*
73  * Print a description of the network interfaces.
74  * NOTE: ifnetaddr is the location of the kernel global "ifnet",
75  * which is a TAILQ_HEAD.
76  */
77 void
78 intpr(interval, ifnetaddr, pfunc)
79 	int interval;
80 	u_long ifnetaddr;
81 	void (*pfunc)(char *);
82 {
83 	struct ifnet ifnet;
84 	union {
85 		struct ifaddr ifa;
86 		struct in_ifaddr in;
87 #ifdef INET6
88 		struct in6_ifaddr in6;
89 #endif /* INET6 */
90 		struct ns_ifaddr ns;
91 		struct iso_ifaddr iso;
92 	} ifaddr;
93 	u_long ifaddraddr;
94 	struct sockaddr *sa;
95 	struct ifnet_head ifhead;	/* TAILQ_HEAD */
96 	char name[IFNAMSIZ + 1];	/* + 1 for `*' */
97 	char hbuf[NI_MAXHOST];		/* for getnameinfo() */
98 #ifdef INET6
99 #ifdef NI_WITHSCOPEID
100 	const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID;
101 #else
102 	const int niflag = NI_NUMERICHOST;
103 #endif
104 #endif
105 
106 	if (ifnetaddr == 0) {
107 		printf("ifnet: symbol not defined\n");
108 		return;
109 	}
110 	if (interval) {
111 		sidewaysintpr((unsigned)interval, ifnetaddr);
112 		return;
113 	}
114 
115 	/*
116 	 * Find the pointer to the first ifnet structure.  Replace
117 	 * the pointer to the TAILQ_HEAD with the actual pointer
118 	 * to the first list element.
119 	 */
120 	if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead))
121 		return;
122 	ifnetaddr = (u_long)ifhead.tqh_first;
123 
124 	if (!sflag & !pflag) {
125 		if (bflag) {
126 			printf("%-5.5s %-5.5s %-13.13s %-17.17s "
127 			       "%10.10s %10.10s",
128 			       "Name", "Mtu", "Network", "Address",
129 			       "Ibytes", "Obytes");
130 		} else {
131 			printf("%-5.5s %-5.5s %-13.13s %-17.17s "
132 			       "%8.8s %5.5s %8.8s %5.5s %5.5s",
133 			       "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
134 			       "Opkts", "Oerrs", "Colls");
135 		}
136 		if (tflag)
137 			printf(" %4.4s", "Time");
138 		if (dflag)
139 			printf(" %5.5s", "Drops");
140 		putchar('\n');
141 	}
142 	ifaddraddr = 0;
143 	while (ifnetaddr || ifaddraddr) {
144 		struct sockaddr_in *sin;
145 #ifdef INET6
146 		struct sockaddr_in6 *sin6;
147 #endif /* INET6 */
148 		char *cp;
149 		int n, m;
150 
151 		if (ifaddraddr == 0) {
152 			if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet))
153 				return;
154 			memmove(name, ifnet.if_xname, IFNAMSIZ);
155 			name[IFNAMSIZ - 1] = '\0';	/* sanity */
156 			ifnetaddr = (u_long)ifnet.if_list.tqe_next;
157 			if (interface != 0 && strcmp(name, interface) != 0)
158 				continue;
159 			cp = strchr(name, '\0');
160 
161 			if (pfunc) {
162 				(*pfunc)(name);
163 				continue;
164 			}
165 
166 			if ((ifnet.if_flags & IFF_UP) == 0)
167 				*cp++ = '*';
168 			*cp = '\0';
169 			ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first;
170 		}
171 		if (vflag)
172 			n = strlen(name) < 5 ? 5 : strlen(name);
173 		else
174 			n = 5;
175 		printf("%-*.*s %-5llu ", n, n, name,
176 		    (unsigned long long)ifnet.if_mtu);
177 		if (ifaddraddr == 0) {
178 			printf("%-13.13s ", "none");
179 			printf("%-17.17s ", "none");
180 		} else {
181 			char hexsep = '.';		/* for hexprint */
182 			static const char hexfmt[] = "%02x%c";	/* for hexprint */
183 			if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
184 				ifaddraddr = 0;
185 				continue;
186 			}
187 #define CP(x) ((char *)(x))
188 			cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
189 			    CP(&ifaddr);
190 			sa = (struct sockaddr *)cp;
191 			switch (sa->sa_family) {
192 			case AF_UNSPEC:
193 				printf("%-13.13s ", "none");
194 				printf("%-17.17s ", "none");
195 				break;
196 			case AF_INET:
197 				sin = (struct sockaddr_in *)sa;
198 #ifdef notdef
199 				/*
200 				 * can't use inet_makeaddr because kernel
201 				 * keeps nets unshifted.
202 				 */
203 				in = inet_makeaddr(ifaddr.in.ia_subnet,
204 					INADDR_ANY);
205 				cp = netname(in.s_addr,
206 					ifaddr.in.ia_subnetmask);
207 #else
208 				cp = netname(ifaddr.in.ia_subnet,
209 					ifaddr.in.ia_subnetmask);
210 #endif
211 				if (vflag)
212 					n = strlen(cp) < 13 ? 13 : strlen(cp);
213 				else
214 					n = 13;
215 				printf("%-*.*s ", n, n, cp);
216 				cp = routename(sin->sin_addr.s_addr);
217 				if (vflag)
218 					n = strlen(cp) < 17 ? 17 : strlen(cp);
219 				else
220 					n = 17;
221 				printf("%-*.*s ", n, n, cp);
222 				if (aflag) {
223 					u_long multiaddr;
224 					struct in_multi inm;
225 
226 					multiaddr = (u_long)
227 					    ifaddr.in.ia_multiaddrs.lh_first;
228 					while (multiaddr != 0) {
229 						kread(multiaddr, (char *)&inm,
230 						   sizeof inm);
231 						printf("\n%25s %-17.17s ", "",
232 						   routename(
233 						      inm.inm_addr.s_addr));
234 						multiaddr =
235 						   (u_long)inm.inm_list.le_next;
236 					}
237 				}
238 				break;
239 #ifdef INET6
240 			case AF_INET6:
241 				sin6 = (struct sockaddr_in6 *)sa;
242 #ifdef __KAME__
243 				if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
244 					sin6->sin6_scope_id =
245 						ntohs(*(u_int16_t *)
246 						  &sin6->sin6_addr.s6_addr[2]);
247 					/* too little width */
248 					if (!vflag)
249 						sin6->sin6_scope_id = 0;
250 					sin6->sin6_addr.s6_addr[2] = 0;
251 					sin6->sin6_addr.s6_addr[3] = 0;
252 				}
253 #endif
254 				cp = netname6(&ifaddr.in6.ia_addr,
255 					&ifaddr.in6.ia_prefixmask.sin6_addr);
256 				if (vflag)
257 					n = strlen(cp) < 13 ? 13 : strlen(cp);
258 				else
259 					n = 13;
260 				printf("%-*.*s ", n, n, cp);
261 				if (getnameinfo((struct sockaddr *)sin6,
262 						sin6->sin6_len,
263 						hbuf, sizeof(hbuf), NULL, 0,
264 						niflag) != 0) {
265 					cp = "?";
266 				} else
267 					cp = hbuf;
268 				if (vflag)
269 					n = strlen(cp) < 17 ? 17 : strlen(cp);
270 				else
271 					n = 17;
272 				printf("%-*.*s ", n, n, cp);
273 				if (aflag) {
274 					u_long multiaddr;
275 					struct in6_multi inm;
276 					struct sockaddr_in6 sin6;
277 
278 					multiaddr = (u_long)
279 					    ifaddr.in6.ia6_multiaddrs.lh_first;
280 					while (multiaddr != 0) {
281 						kread(multiaddr, (char *)&inm,
282 						   sizeof inm);
283 						memset(&sin6, 0, sizeof(sin6));
284 						sin6.sin6_len = sizeof(struct sockaddr_in6);
285 						sin6.sin6_family = AF_INET6;
286 						sin6.sin6_addr = inm.in6m_addr;
287 #ifdef __KAME__
288 						if (IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) {
289 							sin6.sin6_scope_id =
290 							    ntohs(*(u_int16_t *)
291 								&sin6.sin6_addr.s6_addr[2]);
292 							sin6.sin6_addr.s6_addr[2] = 0;
293 							sin6.sin6_addr.s6_addr[3] = 0;
294 						}
295 #endif
296 						if (getnameinfo((struct sockaddr *)&sin6,
297 						    sin6.sin6_len, hbuf,
298 						    sizeof(hbuf), NULL, 0,
299 						    niflag) != 0) {
300 							strlcpy(hbuf, "??",
301 							    sizeof(hbuf));
302 						}
303 						cp = hbuf;
304 						if (vflag)
305 						    n = strlen(cp) < 17
306 							? 17 : strlen(cp);
307 						else
308 						    n = 17;
309 						printf("\n%25s %-*.*s ", "",
310 						    n, n, cp);
311 						multiaddr =
312 						   (u_long)inm.in6m_entry.le_next;
313 					}
314 				}
315 				break;
316 #endif /*INET6*/
317 #ifndef SMALL
318 			case AF_APPLETALK:
319 				printf("atalk:%-7.7s ",
320 				       atalk_print(sa,0x10));
321 				printf("%-17.17s ", atalk_print(sa,0x0b));
322 				break;
323 			case AF_NS:
324 				{
325 				struct sockaddr_ns *sns =
326 					(struct sockaddr_ns *)sa;
327 				u_long net;
328 				char netnum[10];
329 
330 				*(union ns_net *)&net = sns->sns_addr.x_net;
331 				(void)snprintf(netnum, sizeof(netnum), "%xH",
332 				    (u_int32_t)ntohl(net));
333 				upHex(netnum);
334 				printf("ns:%-10s ", netnum);
335 				printf("%-17.17s ",
336 				    ns_phost((struct sockaddr *)sns));
337 				}
338 				break;
339 #endif
340 			case AF_LINK:
341 				printf("%-13.13s ", "<Link>");
342 				if (getnameinfo(sa, sa->sa_len,
343 				    hbuf, sizeof(hbuf), NULL, 0,
344 				    NI_NUMERICHOST) != 0) {
345 					cp = "?";
346 				} else
347 					cp = hbuf;
348 				if (vflag)
349 					n = strlen(cp) < 17 ? 17 : strlen(cp);
350 				else
351 					n = 17;
352 				printf("%-*.*s ", n, n, cp);
353 				break;
354 
355 			default:
356 				m = printf("(%d)", sa->sa_family);
357 				for (cp = sa->sa_len + (char *)sa;
358 					--cp > sa->sa_data && (*cp == 0);) {}
359 				n = cp - sa->sa_data + 1;
360 				cp = sa->sa_data;
361 				while (--n >= 0)
362 					m += printf(hexfmt, *cp++ & 0xff,
363 						    n > 0 ? hexsep : ' ');
364 				m = 32 - m;
365 				while (m-- > 0)
366 					putchar(' ');
367 				break;
368 			}
369 			ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
370 		}
371 		if (bflag) {
372 			printf("%10llu %10llu",
373 				(unsigned long long)ifnet.if_ibytes,
374 				(unsigned long long)ifnet.if_obytes);
375 		} else {
376 			printf("%8llu %5llu %8llu %5llu %5llu",
377 				(unsigned long long)ifnet.if_ipackets,
378 				(unsigned long long)ifnet.if_ierrors,
379 				(unsigned long long)ifnet.if_opackets,
380 				(unsigned long long)ifnet.if_oerrors,
381 				(unsigned long long)ifnet.if_collisions);
382 		}
383 		if (tflag)
384 			printf(" %4d", ifnet.if_timer);
385 		if (dflag)
386 			printf(" %5d", ifnet.if_snd.ifq_drops);
387 		putchar('\n');
388 	}
389 }
390 
391 #define	MAXIF	100
392 struct	iftot {
393 	char ift_name[IFNAMSIZ];	/* interface name */
394 	u_quad_t ift_ip;		/* input packets */
395 	u_quad_t ift_ib;		/* input bytes */
396 	u_quad_t ift_ie;		/* input errors */
397 	u_quad_t ift_op;		/* output packets */
398 	u_quad_t ift_ob;		/* output bytes */
399 	u_quad_t ift_oe;		/* output errors */
400 	u_quad_t ift_co;		/* collisions */
401 	int ift_dr;			/* drops */
402 } iftot[MAXIF];
403 
404 u_char	signalled;			/* set if alarm goes off "early" */
405 
406 /*
407  * Print a running summary of interface statistics.
408  * Repeat display every interval seconds, showing statistics
409  * collected over that interval.  Assumes that interval is non-zero.
410  * First line printed at top of screen is always cumulative.
411  */
412 static void
413 sidewaysintpr(interval, off)
414 	unsigned interval;
415 	u_long off;
416 {
417 	struct itimerval it;
418 	struct ifnet ifnet;
419 	u_long firstifnet;
420 	struct iftot *ip, *total;
421 	int line;
422 	struct iftot *lastif, *sum, *interesting;
423 	struct ifnet_head ifhead;	/* TAILQ_HEAD */
424 	int oldmask;
425 
426 	/*
427 	 * Find the pointer to the first ifnet structure.  Replace
428 	 * the pointer to the TAILQ_HEAD with the actual pointer
429 	 * to the first list element.
430 	 */
431 	if (kread(off, (char *)&ifhead, sizeof ifhead))
432 		return;
433 	firstifnet = (u_long)ifhead.tqh_first;
434 
435 	lastif = iftot;
436 	sum = iftot + MAXIF - 1;
437 	total = sum - 1;
438 	interesting = (interface == NULL) ? iftot : NULL;
439 	for (off = firstifnet, ip = iftot; off;) {
440 		if (kread(off, (char *)&ifnet, sizeof ifnet))
441 			break;
442 		memset(ip->ift_name, 0, sizeof(ip->ift_name));
443 		snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname);
444 		if (interface && strcmp(ifnet.if_xname, interface) == 0)
445 			interesting = ip;
446 		ip++;
447 		if (ip >= iftot + MAXIF - 2)
448 			break;
449 		off = (u_long)ifnet.if_list.tqe_next;
450 	}
451 	if (interesting == NULL) {
452 		fprintf(stderr, "%s: %s: unknown interface\n",
453 		    getprogname(), interface);
454 		exit(1);
455 	}
456 	lastif = ip;
457 
458 	(void)signal(SIGALRM, catchalarm);
459 	signalled = NO;
460 
461 	it.it_interval.tv_sec = it.it_value.tv_sec = interval;
462 	it.it_interval.tv_usec = it.it_value.tv_usec = 0;
463 	setitimer(ITIMER_REAL, &it, NULL);
464 
465 banner:
466 	if (bflag)
467 		printf("%7.7s in %8.8s %6.6s out %5.5s",
468 		    interesting->ift_name, " ",
469 		    interesting->ift_name, " ");
470 	else
471 		printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
472 		    interesting->ift_name, " ",
473 		    interesting->ift_name, " ", " ");
474 	if (dflag)
475 		printf(" %5.5s", " ");
476 	if (lastif - iftot > 0) {
477 		if (bflag)
478 			printf("  %7.7s in %8.8s %6.6s out %5.5s",
479 			    "total", " ", "total", " ");
480 		else
481 			printf("  %5.5s in %5.5s%5.5s out %5.5s %5.5s",
482 			    "total", " ", "total", " ", " ");
483 		if (dflag)
484 			printf(" %5.5s", " ");
485 	}
486 	for (ip = iftot; ip < iftot + MAXIF; ip++) {
487 		ip->ift_ip = 0;
488 		ip->ift_ib = 0;
489 		ip->ift_ie = 0;
490 		ip->ift_op = 0;
491 		ip->ift_ob = 0;
492 		ip->ift_oe = 0;
493 		ip->ift_co = 0;
494 		ip->ift_dr = 0;
495 	}
496 	putchar('\n');
497 	if (bflag)
498 		printf("%10.10s %8.8s %10.10s %5.5s",
499 		    "bytes", " ", "bytes", " ");
500 	else
501 		printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
502 		    "packets", "errs", "packets", "errs", "colls");
503 	if (dflag)
504 		printf(" %5.5s", "drops");
505 	if (lastif - iftot > 0) {
506 		if (bflag)
507 			printf("  %10.10s %8.8s %10.10s %5.5s",
508 			    "bytes", " ", "bytes", " ");
509 		else
510 			printf("  %8.8s %5.5s %8.8s %5.5s %5.5s",
511 			    "packets", "errs", "packets", "errs", "colls");
512 		if (dflag)
513 			printf(" %5.5s", "drops");
514 	}
515 	putchar('\n');
516 	fflush(stdout);
517 	line = 0;
518 loop:
519 	sum->ift_ip = 0;
520 	sum->ift_ib = 0;
521 	sum->ift_ie = 0;
522 	sum->ift_op = 0;
523 	sum->ift_ob = 0;
524 	sum->ift_oe = 0;
525 	sum->ift_co = 0;
526 	sum->ift_dr = 0;
527 	for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
528 		if (kread(off, (char *)&ifnet, sizeof ifnet)) {
529 			off = 0;
530 			continue;
531 		}
532 		if (ip == interesting) {
533 			if (bflag) {
534 				printf("%10llu %8.8s %10llu %5.5s",
535 				    (unsigned long long)(ifnet.if_ibytes -
536 					ip->ift_ib), " ",
537 				    (unsigned long long)(ifnet.if_obytes -
538 					ip->ift_ob), " ");
539 			} else {
540 				printf("%8llu %5llu %8llu %5llu %5llu",
541 				    (unsigned long long)
542 					(ifnet.if_ipackets - ip->ift_ip),
543 				    (unsigned long long)
544 					(ifnet.if_ierrors - ip->ift_ie),
545 				    (unsigned long long)
546 					(ifnet.if_opackets - ip->ift_op),
547 				    (unsigned long long)
548 					(ifnet.if_oerrors - ip->ift_oe),
549 				    (unsigned long long)
550 					(ifnet.if_collisions - ip->ift_co));
551 			}
552 			if (dflag)
553 				printf(" %5llu",
554 				    (unsigned long long)
555 					(ifnet.if_snd.ifq_drops - ip->ift_dr));
556 		}
557 		ip->ift_ip = ifnet.if_ipackets;
558 		ip->ift_ib = ifnet.if_ibytes;
559 		ip->ift_ie = ifnet.if_ierrors;
560 		ip->ift_op = ifnet.if_opackets;
561 		ip->ift_ob = ifnet.if_obytes;
562 		ip->ift_oe = ifnet.if_oerrors;
563 		ip->ift_co = ifnet.if_collisions;
564 		ip->ift_dr = ifnet.if_snd.ifq_drops;
565 		sum->ift_ip += ip->ift_ip;
566 		sum->ift_ib += ip->ift_ib;
567 		sum->ift_ie += ip->ift_ie;
568 		sum->ift_op += ip->ift_op;
569 		sum->ift_ob += ip->ift_ob;
570 		sum->ift_oe += ip->ift_oe;
571 		sum->ift_co += ip->ift_co;
572 		sum->ift_dr += ip->ift_dr;
573 		off = (u_long)ifnet.if_list.tqe_next;
574 	}
575 	if (lastif - iftot > 0) {
576 		if (bflag) {
577 			printf("  %10llu %8.8s %10llu %5.5s",
578 			    (unsigned long long)
579 				(sum->ift_ib - total->ift_ib), " ",
580 			    (unsigned long long)
581 				(sum->ift_ob - total->ift_ob), " ");
582 		} else {
583 			printf("  %8llu %5llu %8llu %5llu %5llu",
584 			    (unsigned long long)
585 				(sum->ift_ip - total->ift_ip),
586 			    (unsigned long long)
587 				(sum->ift_ie - total->ift_ie),
588 			    (unsigned long long)
589 				(sum->ift_op - total->ift_op),
590 			    (unsigned long long)
591 				(sum->ift_oe - total->ift_oe),
592 			    (unsigned long long)
593 				(sum->ift_co - total->ift_co));
594 		}
595 		if (dflag)
596 			printf(" %5llu",
597 			    (unsigned long long)(sum->ift_dr - total->ift_dr));
598 	}
599 	*total = *sum;
600 	putchar('\n');
601 	fflush(stdout);
602 	line++;
603 	oldmask = sigblock(sigmask(SIGALRM));
604 	if (! signalled) {
605 		sigpause(0);
606 	}
607 	sigsetmask(oldmask);
608 	signalled = NO;
609 	if (line == 21)
610 		goto banner;
611 	goto loop;
612 	/*NOTREACHED*/
613 }
614 
615 /*
616  * Called if an interval expires before sidewaysintpr has completed a loop.
617  * Sets a flag to not wait for the alarm.
618  */
619 static void
620 catchalarm(signo)
621 	int signo;
622 {
623 
624 	signalled = YES;
625 }
626