1 /* 2 * Copyright (c) 1983, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)if.c 8.3 (Berkeley) 4/28/95 34 * $FreeBSD: src/usr.bin/netstat/if.c,v 1.32.2.9 2001/09/17 14:35:46 ru Exp $ 35 * $DragonFly: src/usr.bin/netstat/if.c,v 1.4 2003/11/14 09:56:03 hmp Exp $ 36 */ 37 38 #include <sys/types.h> 39 #include <sys/protosw.h> 40 #include <sys/socket.h> 41 #include <sys/sysctl.h> 42 #include <sys/time.h> 43 44 #include <net/if.h> 45 #include <net/if_var.h> 46 #include <net/if_dl.h> 47 #include <net/if_types.h> 48 #include <net/bridge/bridge.h> 49 #include <net/ethernet.h> 50 #include <netinet/in.h> 51 #include <netinet/in_var.h> 52 #include <netproto/ipx/ipx.h> 53 #include <netproto/ipx/ipx_if.h> 54 #ifdef NS 55 #include <netproto/ns/ns.h> 56 #include <netproto/ns/ns_if.h> 57 #endif 58 #ifdef ISO 59 #include <netiso/iso.h> 60 #include <netiso/iso_var.h> 61 #endif 62 #include <arpa/inet.h> 63 64 #include <signal.h> 65 #include <stdio.h> 66 #include <stdlib.h> 67 #include <string.h> 68 #include <unistd.h> 69 70 #include "netstat.h" 71 72 #define YES 1 73 #define NO 0 74 75 static void sidewaysintpr (u_int, u_long); 76 static void catchalarm (int); 77 78 #ifdef INET6 79 char *netname6 (struct sockaddr_in6 *, struct in6_addr *); 80 static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */ 81 static int bdg_done; 82 #endif 83 84 /* print bridge statistics */ 85 void 86 bdg_stats(u_long dummy __unused, char *name, int af __unused) 87 { 88 int i; 89 size_t slen ; 90 struct bdg_stats s ; 91 int mib[4] ; 92 93 slen = sizeof(s); 94 95 mib[0] = CTL_NET ; 96 mib[1] = PF_LINK ; 97 mib[2] = IFT_ETHER ; 98 mib[3] = PF_BDG ; 99 if (sysctl(mib,4, &s,&slen,NULL,0)==-1) 100 return ; /* no bridging */ 101 #ifdef INET6 102 if (bdg_done != 0) 103 return; 104 else 105 bdg_done = 1; 106 #endif 107 printf("-- Bridging statistics (%s) --\n", name) ; 108 printf( 109 "Name In Out Forward Drop Bcast Mcast Local Unknown\n"); 110 for (i = 0 ; i < 16 ; i++) { 111 if (s.s[i].name[0]) 112 printf("%-6s %9ld%9ld%9ld%9ld%9ld%9ld%9ld%9ld\n", 113 s.s[i].name, 114 s.s[i].p_in[(int)BDG_IN], 115 s.s[i].p_in[(int)BDG_OUT], 116 s.s[i].p_in[(int)BDG_FORWARD], 117 s.s[i].p_in[(int)BDG_DROP], 118 s.s[i].p_in[(int)BDG_BCAST], 119 s.s[i].p_in[(int)BDG_MCAST], 120 s.s[i].p_in[(int)BDG_LOCAL], 121 s.s[i].p_in[(int)BDG_UNKNOWN] ); 122 } 123 } 124 125 126 127 128 /* 129 * Display a formatted value, or a '-' in the same space. 130 */ 131 static void 132 show_stat(const char *fmt, int width, u_long value, short showvalue) 133 { 134 char newfmt[32]; 135 136 /* Construct the format string */ 137 if (showvalue) { 138 sprintf(newfmt, "%%%d%s", width, fmt); 139 printf(newfmt, value); 140 } else { 141 sprintf(newfmt, "%%%ds", width); 142 printf(newfmt, "-"); 143 } 144 } 145 146 147 148 /* 149 * Print a description of the network interfaces. 150 */ 151 void 152 intpr(int interval, u_long ifnetaddr, void (*pfunc)(char *)) 153 { 154 struct ifnet ifnet; 155 struct ifnethead ifnethead; 156 union { 157 struct ifaddr ifa; 158 struct in_ifaddr in; 159 #ifdef INET6 160 struct in6_ifaddr in6; 161 #endif 162 struct ipx_ifaddr ipx; 163 #ifdef NS 164 struct ns_ifaddr ns; 165 #endif 166 #ifdef ISO 167 struct iso_ifaddr iso; 168 #endif 169 } ifaddr; 170 u_long ifaddraddr; 171 u_long ifaddrfound; 172 u_long ifnetfound; 173 u_long opackets; 174 u_long ipackets; 175 u_long obytes; 176 u_long ibytes; 177 u_long oerrors; 178 u_long ierrors; 179 u_long collisions; 180 short timer; 181 int drops; 182 struct sockaddr *sa = NULL; 183 char name[32], tname[16]; 184 short network_layer; 185 short link_layer; 186 187 if (ifnetaddr == 0) { 188 printf("ifnet: symbol not defined\n"); 189 return; 190 } 191 if (interval) { 192 sidewaysintpr((unsigned)interval, ifnetaddr); 193 return; 194 } 195 if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead)) 196 return; 197 ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead); 198 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet)) 199 return; 200 201 if (!pfunc) { 202 printf("%-7.7s %-5.5s %-13.13s %-15.15s %8.8s %5.5s", 203 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs"); 204 if (bflag) 205 printf(" %10.10s","Ibytes"); 206 printf(" %8.8s %5.5s", "Opkts", "Oerrs"); 207 if (bflag) 208 printf(" %10.10s","Obytes"); 209 printf(" %5s", "Coll"); 210 if (tflag) 211 printf(" %s", "Time"); 212 if (dflag) 213 printf(" %s", "Drop"); 214 putchar('\n'); 215 } 216 ifaddraddr = 0; 217 while (ifnetaddr || ifaddraddr) { 218 struct sockaddr_in *sin; 219 #ifdef INET6 220 struct sockaddr_in6 *sin6; 221 #endif 222 register char *cp; 223 int n, m; 224 225 network_layer = 0; 226 link_layer = 0; 227 228 if (ifaddraddr == 0) { 229 ifnetfound = ifnetaddr; 230 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) || 231 kread((u_long)ifnet.if_name, tname, 16)) 232 return; 233 tname[15] = '\0'; 234 ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link); 235 snprintf(name, 32, "%s%d", tname, ifnet.if_unit); 236 if (interface != 0 && (strcmp(name, interface) != 0)) 237 continue; 238 cp = index(name, '\0'); 239 240 if (pfunc) { 241 (*pfunc)(name); 242 continue; 243 } 244 245 if ((ifnet.if_flags&IFF_UP) == 0) 246 *cp++ = '*'; 247 *cp = '\0'; 248 ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead); 249 } 250 ifaddrfound = ifaddraddr; 251 252 /* 253 * Get the interface stats. These may get 254 * overriden below on a per-interface basis. 255 */ 256 opackets = ifnet.if_opackets; 257 ipackets = ifnet.if_ipackets; 258 obytes = ifnet.if_obytes; 259 ibytes = ifnet.if_ibytes; 260 oerrors = ifnet.if_oerrors; 261 ierrors = ifnet.if_ierrors; 262 collisions = ifnet.if_collisions; 263 timer = ifnet.if_timer; 264 drops = ifnet.if_snd.ifq_drops; 265 266 if (ifaddraddr == 0) { 267 printf("%-7.7s %-5lu ", name, ifnet.if_mtu); 268 printf("%-13.13s ", "none"); 269 printf("%-15.15s ", "none"); 270 } else { 271 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 272 ifaddraddr = 0; 273 continue; 274 } 275 #define CP(x) ((char *)(x)) 276 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + 277 CP(&ifaddr); 278 sa = (struct sockaddr *)cp; 279 if (af != AF_UNSPEC && sa->sa_family != af) { 280 ifaddraddr = 281 (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link); 282 continue; 283 } 284 printf("%-7.7s %-5lu ", name, ifnet.if_mtu); 285 switch (sa->sa_family) { 286 case AF_UNSPEC: 287 printf("%-13.13s ", "none"); 288 printf("%-15.15s ", "none"); 289 break; 290 case AF_INET: 291 sin = (struct sockaddr_in *)sa; 292 #ifdef notdef 293 /* can't use inet_makeaddr because kernel 294 * keeps nets unshifted. 295 */ 296 in = inet_makeaddr(ifaddr.in.ia_subnet, 297 INADDR_ANY); 298 printf("%-13.13s ", netname(in.s_addr, 299 ifaddr.in.ia_subnetmask)); 300 #else 301 printf("%-13.13s ", 302 netname(htonl(ifaddr.in.ia_subnet), 303 ifaddr.in.ia_subnetmask)); 304 #endif 305 printf("%-15.15s ", 306 routename(sin->sin_addr.s_addr)); 307 308 network_layer = 1; 309 break; 310 #ifdef INET6 311 case AF_INET6: 312 sin6 = (struct sockaddr_in6 *)sa; 313 printf("%-11.11s ", 314 netname6(&ifaddr.in6.ia_addr, 315 &ifaddr.in6.ia_prefixmask.sin6_addr)); 316 printf("%-17.17s ", 317 (char *)inet_ntop(AF_INET6, 318 &sin6->sin6_addr, 319 ntop_buf, sizeof(ntop_buf))); 320 321 network_layer = 1; 322 break; 323 #endif /*INET6*/ 324 case AF_IPX: 325 { 326 struct sockaddr_ipx *sipx = 327 (struct sockaddr_ipx *)sa; 328 u_long net; 329 char netnum[10]; 330 331 *(union ipx_net *) &net = sipx->sipx_addr.x_net; 332 sprintf(netnum, "%lx", (u_long)ntohl(net)); 333 printf("ipx:%-8s ", netnum); 334 /* printf("ipx:%-8s ", netname(net, 0L)); */ 335 printf("%-15s ", 336 ipx_phost((struct sockaddr *)sipx)); 337 } 338 break; 339 340 case AF_APPLETALK: 341 printf("atalk:%-12.12s ",atalk_print(sa,0x10) ); 342 printf("%-9.9s ",atalk_print(sa,0x0b) ); 343 break; 344 #ifdef NS 345 case AF_NS: 346 { 347 struct sockaddr_ns *sns = 348 (struct sockaddr_ns *)sa; 349 u_long net; 350 char netnum[10]; 351 352 *(union ns_net *) &net = sns->sns_addr.x_net; 353 sprintf(netnum, "%lxH", ntohl(net)); 354 upHex(netnum); 355 printf("ns:%-8s ", netnum); 356 printf("%-15s ", 357 ns_phost((struct sockaddr *)sns)); 358 } 359 break; 360 #endif 361 case AF_LINK: 362 { 363 struct sockaddr_dl *sdl = 364 (struct sockaddr_dl *)sa; 365 char linknum[10]; 366 cp = (char *)LLADDR(sdl); 367 n = sdl->sdl_alen; 368 sprintf(linknum, "<Link#%d>", sdl->sdl_index); 369 m = printf("%-11.11s ", linknum); 370 } 371 goto hexprint; 372 default: 373 m = printf("(%d)", sa->sa_family); 374 for (cp = sa->sa_len + (char *)sa; 375 --cp > sa->sa_data && (*cp == 0);) {} 376 n = cp - sa->sa_data + 1; 377 cp = sa->sa_data; 378 hexprint: 379 while (--n >= 0) 380 m += printf("%02x%c", *cp++ & 0xff, 381 n > 0 ? ':' : ' '); 382 m = 30 - m; 383 while (m-- > 0) 384 putchar(' '); 385 386 link_layer = 1; 387 break; 388 } 389 390 /* 391 * Fixup the statistics for interfaces that 392 * update stats for their network addresses 393 */ 394 if (network_layer) { 395 opackets = ifaddr.in.ia_ifa.if_opackets; 396 ipackets = ifaddr.in.ia_ifa.if_ipackets; 397 obytes = ifaddr.in.ia_ifa.if_obytes; 398 ibytes = ifaddr.in.ia_ifa.if_ibytes; 399 } 400 401 ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link); 402 } 403 404 show_stat("lu", 8, ipackets, link_layer|network_layer); 405 printf(" "); 406 show_stat("lu", 5, ierrors, link_layer); 407 printf(" "); 408 if (bflag) { 409 show_stat("lu", 10, ibytes, link_layer|network_layer); 410 printf(" "); 411 } 412 show_stat("lu", 8, opackets, link_layer|network_layer); 413 printf(" "); 414 show_stat("lu", 5, oerrors, link_layer); 415 printf(" "); 416 if (bflag) { 417 show_stat("lu", 10, obytes, link_layer|network_layer); 418 printf(" "); 419 } 420 show_stat("lu", 5, collisions, link_layer); 421 if (tflag) { 422 printf(" "); 423 show_stat("d", 3, timer, link_layer); 424 } 425 if (dflag) { 426 printf(" "); 427 show_stat("d", 3, drops, link_layer); 428 } 429 putchar('\n'); 430 if (aflag && ifaddrfound) { 431 /* 432 * Print family's multicast addresses 433 */ 434 u_long multiaddr; 435 struct ifmultiaddr ifma; 436 union { 437 struct sockaddr sa; 438 struct sockaddr_in in; 439 #ifdef INET6 440 struct sockaddr_in6 in6; 441 #endif /* INET6 */ 442 struct sockaddr_dl dl; 443 } msa; 444 const char *fmt; 445 446 for(multiaddr = (u_long)ifnet.if_multiaddrs.lh_first; 447 multiaddr; 448 multiaddr = (u_long)ifma.ifma_link.le_next) { 449 if (kread(multiaddr, (char *)&ifma, 450 sizeof ifma)) 451 break; 452 if (kread((u_long)ifma.ifma_addr, (char *)&msa, 453 sizeof msa)) 454 break; 455 if (msa.sa.sa_family != sa->sa_family) 456 continue; 457 458 fmt = 0; 459 switch (msa.sa.sa_family) { 460 case AF_INET: 461 fmt = routename(msa.in.sin_addr.s_addr); 462 break; 463 #ifdef INET6 464 case AF_INET6: 465 printf("%23s %-19.19s(refs: %d)\n", "", 466 inet_ntop(AF_INET6, 467 &msa.in6.sin6_addr, 468 ntop_buf, 469 sizeof(ntop_buf)), 470 ifma.ifma_refcount); 471 break; 472 #endif /* INET6 */ 473 case AF_LINK: 474 switch (msa.dl.sdl_type) { 475 case IFT_ETHER: 476 case IFT_FDDI: 477 fmt = ether_ntoa( 478 (struct ether_addr *) 479 LLADDR(&msa.dl)); 480 break; 481 } 482 break; 483 } 484 if (fmt) 485 printf("%23s %s\n", "", fmt); 486 } 487 } 488 } 489 } 490 491 struct iftot { 492 SLIST_ENTRY(iftot) chain; 493 char ift_name[16]; /* interface name */ 494 u_long ift_ip; /* input packets */ 495 u_long ift_ie; /* input errors */ 496 u_long ift_op; /* output packets */ 497 u_long ift_oe; /* output errors */ 498 u_long ift_co; /* collisions */ 499 u_int ift_dr; /* drops */ 500 u_long ift_ib; /* input bytes */ 501 u_long ift_ob; /* output bytes */ 502 }; 503 504 u_char signalled; /* set if alarm goes off "early" */ 505 506 /* 507 * Print a running summary of interface statistics. 508 * Repeat display every interval seconds, showing statistics 509 * collected over that interval. Assumes that interval is non-zero. 510 * First line printed at top of screen is always cumulative. 511 * XXX - should be rewritten to use ifmib(4). 512 */ 513 static void 514 sidewaysintpr(unsigned interval, u_long off) 515 { 516 struct ifnet ifnet; 517 u_long firstifnet; 518 struct ifnethead ifnethead; 519 struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting; 520 register int line; 521 int oldmask, first; 522 u_long interesting_off; 523 524 if (kread(off, (char *)&ifnethead, sizeof ifnethead)) 525 return; 526 firstifnet = (u_long)TAILQ_FIRST(&ifnethead); 527 528 if ((iftot = malloc(sizeof(struct iftot))) == NULL) { 529 printf("malloc failed\n"); 530 exit(1); 531 } 532 memset(iftot, 0, sizeof(struct iftot)); 533 534 interesting = NULL; 535 interesting_off = 0; 536 for (off = firstifnet, ip = iftot; off;) { 537 char name[16], tname[16]; 538 539 if (kread(off, (char *)&ifnet, sizeof ifnet)) 540 break; 541 if (kread((u_long)ifnet.if_name, tname, 16)) 542 break; 543 tname[15] = '\0'; 544 snprintf(name, 16, "%s%d", tname, ifnet.if_unit); 545 if (interface && strcmp(name, interface) == 0) { 546 interesting = ip; 547 interesting_off = off; 548 } 549 snprintf(ip->ift_name, 16, "(%s)", name);; 550 if ((ipn = malloc(sizeof(struct iftot))) == NULL) { 551 printf("malloc failed\n"); 552 exit(1); 553 } 554 memset(ipn, 0, sizeof(struct iftot)); 555 SLIST_NEXT(ip, chain) = ipn; 556 ip = ipn; 557 off = (u_long)TAILQ_NEXT(&ifnet, if_link); 558 } 559 if ((total = malloc(sizeof(struct iftot))) == NULL) { 560 printf("malloc failed\n"); 561 exit(1); 562 } 563 memset(total, 0, sizeof(struct iftot)); 564 if ((sum = malloc(sizeof(struct iftot))) == NULL) { 565 printf("malloc failed\n"); 566 exit(1); 567 } 568 memset(sum, 0, sizeof(struct iftot)); 569 570 571 (void)signal(SIGALRM, catchalarm); 572 signalled = NO; 573 (void)alarm(interval); 574 first = 1; 575 banner: 576 printf("%17s %14s %16s", "input", 577 interesting ? interesting->ift_name : "(Total)", "output"); 578 putchar('\n'); 579 printf("%10s %5s %10s %10s %5s %10s %5s", 580 "packets", "errs", "bytes", "packets", "errs", "bytes", "colls"); 581 if (dflag) 582 printf(" %5.5s", "drops"); 583 putchar('\n'); 584 fflush(stdout); 585 line = 0; 586 loop: 587 if (interesting != NULL) { 588 ip = interesting; 589 if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) { 590 printf("???\n"); 591 exit(1); 592 }; 593 if (!first) { 594 printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu", 595 ifnet.if_ipackets - ip->ift_ip, 596 ifnet.if_ierrors - ip->ift_ie, 597 ifnet.if_ibytes - ip->ift_ib, 598 ifnet.if_opackets - ip->ift_op, 599 ifnet.if_oerrors - ip->ift_oe, 600 ifnet.if_obytes - ip->ift_ob, 601 ifnet.if_collisions - ip->ift_co); 602 if (dflag) 603 printf(" %5u", ifnet.if_snd.ifq_drops - ip->ift_dr); 604 } 605 ip->ift_ip = ifnet.if_ipackets; 606 ip->ift_ie = ifnet.if_ierrors; 607 ip->ift_ib = ifnet.if_ibytes; 608 ip->ift_op = ifnet.if_opackets; 609 ip->ift_oe = ifnet.if_oerrors; 610 ip->ift_ob = ifnet.if_obytes; 611 ip->ift_co = ifnet.if_collisions; 612 ip->ift_dr = ifnet.if_snd.ifq_drops; 613 } else { 614 sum->ift_ip = 0; 615 sum->ift_ie = 0; 616 sum->ift_ib = 0; 617 sum->ift_op = 0; 618 sum->ift_oe = 0; 619 sum->ift_ob = 0; 620 sum->ift_co = 0; 621 sum->ift_dr = 0; 622 for (off = firstifnet, ip = iftot; 623 off && SLIST_NEXT(ip, chain) != NULL; 624 ip = SLIST_NEXT(ip, chain)) { 625 if (kread(off, (char *)&ifnet, sizeof ifnet)) { 626 off = 0; 627 continue; 628 } 629 sum->ift_ip += ifnet.if_ipackets; 630 sum->ift_ie += ifnet.if_ierrors; 631 sum->ift_ib += ifnet.if_ibytes; 632 sum->ift_op += ifnet.if_opackets; 633 sum->ift_oe += ifnet.if_oerrors; 634 sum->ift_ob += ifnet.if_obytes; 635 sum->ift_co += ifnet.if_collisions; 636 sum->ift_dr += ifnet.if_snd.ifq_drops; 637 off = (u_long)TAILQ_NEXT(&ifnet, if_link); 638 } 639 if (!first) { 640 printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu", 641 sum->ift_ip - total->ift_ip, 642 sum->ift_ie - total->ift_ie, 643 sum->ift_ib - total->ift_ib, 644 sum->ift_op - total->ift_op, 645 sum->ift_oe - total->ift_oe, 646 sum->ift_ob - total->ift_ob, 647 sum->ift_co - total->ift_co); 648 if (dflag) 649 printf(" %5u", sum->ift_dr - total->ift_dr); 650 } 651 *total = *sum; 652 } 653 if (!first) 654 putchar('\n'); 655 fflush(stdout); 656 oldmask = sigblock(sigmask(SIGALRM)); 657 if (! signalled) { 658 sigpause(0); 659 } 660 sigsetmask(oldmask); 661 signalled = NO; 662 (void)alarm(interval); 663 line++; 664 first = 0; 665 if (line == 21) 666 goto banner; 667 else 668 goto loop; 669 /*NOTREACHED*/ 670 } 671 672 /* 673 * Called if an interval expires before sidewaysintpr has completed a loop. 674 * Sets a flag to not wait for the alarm. 675 */ 676 static void 677 catchalarm(int signo __unused) 678 { 679 signalled = YES; 680 } 681