X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fsonar.c;h=3a3e6ce883e243eae5a35a9a231b356412cd8c97;hb=a94197e76a5dea5cb60542840809d6c20d0abbf3;hp=5ccbc44c079b4219031f66befd7d4c618a9f1208;hpb=14627f4038ada5d11456f3770090f3c39740d70f;p=xscreensaver diff --git a/hacks/sonar.c b/hacks/sonar.c index 5ccbc44c..3a3e6ce8 100644 --- a/hacks/sonar.c +++ b/hacks/sonar.c @@ -28,7 +28,8 @@ * - plot the process table, by process size, cpu usage, or total time; * - plot the logged on users by idle time or cpu usage. * - * Copyright (C) 1998 by Stephen Martin (smartin@vanderfleet-martin.net). + * Copyright (C) 1998, 2001 + * by Stephen Martin (smartin@vanderfleet-martin.net). * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that @@ -37,7 +38,7 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * $Revision: 1.17 $ + * $Revision: 1.21 $ * * Version 1.0 April 27, 1998. * - Initial version @@ -143,6 +144,18 @@ # undef HAVE_PING #endif + +#ifdef HAVE_PING +# if defined(__DECC) || defined(_IP_VHL) + /* This is how you do it on DEC C, and possibly some BSD systems. */ +# define IP_HDRLEN(ip) ((ip)->ip_vhl & 0x0F) +# else + /* This is how you do it on everything else. */ +# define IP_HDRLEN(ip) ((ip)->ip_hl) +# endif +#endif /* HAVE_PING */ + + /* Forward References */ #ifdef HAVE_PING @@ -217,7 +230,9 @@ void *sensor_info; /* Information about the sensor */ typedef struct ping_target { char *name; /* The name of the target */ +#ifdef HAVE_PING struct sockaddr address; /* The address of the target */ +#endif /* HAVE_PING */ struct ping_target *next; /* The next one in the list */ } ping_target; @@ -433,47 +448,91 @@ findNode(Bogie *bl, char *name) static int lookupHost(ping_target *target) { - struct hostent *hent; + struct sockaddr_in *iaddr; - /* Local Variables */ + int iip[4]; + char c; - struct sockaddr_in *iaddr; + iaddr = (struct sockaddr_in *) &(target->address); + iaddr->sin_family = AF_INET; - /* Set up the target address we first assume that the name is the - IP address as a string */ + if (4 == sscanf(target->name, "%d.%d.%d.%d%c", + &iip[0], &iip[1], &iip[2], &iip[3], &c)) + { + /* It's an IP address. + */ + unsigned char ip[4]; + + ip[0] = iip[0]; + ip[1] = iip[1]; + ip[2] = iip[2]; + ip[3] = iip[3]; + + if (ip[3] == 0) + { + if (debug_p > 1) + fprintf (stderr, "%s: ignoring bogus IP %s\n", + progname, target->name); + return 0; + } - iaddr = (struct sockaddr_in *) &(target->address); - iaddr->sin_family = AF_INET; - if ((iaddr->sin_addr.s_addr = inet_addr(target->name)) >= 0) { - char ip[4]; - ip[3] = iaddr->sin_addr.s_addr >> 24 & 255; - ip[2] = iaddr->sin_addr.s_addr >> 16 & 255; - ip[1] = iaddr->sin_addr.s_addr >> 8 & 255; - ip[0] = iaddr->sin_addr.s_addr & 255; + iaddr->sin_addr.s_addr = ((ip[3] << 24) | + (ip[2] << 16) | + (ip[1] << 8) | + (ip[0])); hent = gethostbyaddr (ip, 4, AF_INET); - if (hent && hent->h_name && *hent->h_name) { + + if (debug_p > 1) + fprintf (stderr, "%s: %s => %s\n", + progname, target->name, + ((hent && hent->h_name && *hent->h_name) + ? hent->h_name : "")); + + if (hent && hent->h_name && *hent->h_name) target->name = strdup (hent->h_name); - return 1; - } } + else + { + /* It's a host name. + */ + hent = gethostbyname (target->name); + if (!hent) + { + fprintf (stderr, "%s: could not resolve host: %s\n", + progname, target->name); + return 0; + } - /* Conversion of IP address failed, try to look the host up by name */ + memcpy (&iaddr->sin_addr, hent->h_addr_list[0], + sizeof(iaddr->sin_addr)); - hent = gethostbyname(target->name); - if (hent == NULL) { - fprintf(stderr, "%s: could not resolve host %s\n", - progname, target->name); - return 0; + if (debug_p > 1) + fprintf (stderr, "%s: %s => %d.%d.%d.%d\n", + progname, target->name, + iaddr->sin_addr.s_addr & 255, + iaddr->sin_addr.s_addr >> 8 & 255, + iaddr->sin_addr.s_addr >> 16 & 255, + iaddr->sin_addr.s_addr >> 24 & 255); } - memcpy(&iaddr->sin_addr, hent->h_addr_list[0], - sizeof(iaddr->sin_addr)); + return 1; +} - /* Done */ - return 1; +static void +print_host (FILE *out, unsigned long ip, const char *name) +{ + char ips[50]; + sprintf (ips, "%d.%d.%d.%d", + (ip) & 255, + (ip >> 8) & 255, + (ip >> 16) & 255, + (ip >> 24) & 255); + if (!name || !*name) name = ""; + fprintf (out, "%-16s %s\n", ips, name); } + /* * Create a target for a host. * @@ -508,15 +567,29 @@ newHost(char *name) if (! lookupHost(target)) goto target_init_error; + /* Don't ever use loopback (127.0.0) hosts */ + { + struct sockaddr_in *iaddr = (struct sockaddr_in *) &(target->address); + unsigned long ip = iaddr->sin_addr.s_addr; + if ((ip & 255) == 127 && + ((ip >> 8) & 255) == 0 && + ((ip >> 16) & 255) == 0) + { + if (debug_p) + fprintf (stderr, "%s: ignoring loopback host %s\n", + progname, target->name); + goto target_init_error; + } + } + /* Done */ if (debug_p) { struct sockaddr_in *iaddr = (struct sockaddr_in *) &(target->address); unsigned long ip = iaddr->sin_addr.s_addr; - fprintf (stderr, "%s: added host %d.%d.%d.%d (%s)\n", progname, - ip & 255, ip >> 8 & 255, ip >> 16 & 255, ip >> 24 & 255, - target->name); + fprintf (stderr, "%s: added ", progname); + print_host (stderr, ip, target->name); } return target; @@ -590,8 +663,8 @@ readPingHostsFile(char *fname) /* Get the name and address */ name = addr = NULL; - if ((addr = strtok(buf, " \t\n")) != NULL) - name = strtok(NULL, " \t\n"); + if ((addr = strtok(buf, " ,;\t\n")) != NULL) + name = strtok(NULL, " ,;\t\n"); else continue; @@ -609,7 +682,22 @@ readPingHostsFile(char *fname) addr = NULL; } } - /*printf ("\"%s\" \"%s\"\n", name, addr);*/ + + /* If the name is all digits, it's not a name. */ + if (name) + { + const char *s; + for (s = name; *s; s++) + if (*s < '0' || *s > '9') + break; + if (! *s) + { + if (debug_p > 1) + fprintf (stderr, "%s: skipping bogus name \"%s\" (%s)\n", + progname, name, addr); + name = NULL; + } + } /* Create a new target using first the name then the address */ @@ -657,8 +745,10 @@ delete_duplicate_hosts (ping_target *list) if (ip1 == ip2) { if (debug_p) - fprintf (stderr, "%s: deleted duplicate: %s\n", - progname, rest2->next->name); + { + fprintf (stderr, "%s: deleted duplicate: ", progname); + print_host (stderr, ip2, rest2->next->name); + } rest2->next = rest2->next->next; } } @@ -699,7 +789,7 @@ subnetHostsList(int base, int subnet_width) fprintf (stderr, "%s: pinging %u hosts is a bad idea; please use a subnet mask of 24 bits\n" " or more (255 hosts max.)\n", - progname, 1L << (32 - subnet_width)); + progname, (1L << (32 - subnet_width)) - 1); exit (1); } else if (subnet_width > 30) @@ -742,6 +832,17 @@ subnetHostsList(int base, int subnet_width) (((unsigned char) hent->h_addr_list[0][2]) << 8) | (((unsigned char) hent->h_addr_list[0][3]))); + if (base == ((127 << 24) | 1)) + { + fprintf (stderr, + "%s: unable to determine local subnet address: \"%s\"\n" + " resolves to loopback address %d.%d.%d.%d.\n", + progname, hostname, + (base >> 24) & 255, (base >> 16) & 255, + (base >> 8) & 255, (base ) & 255); + return NULL; + } + for (i = 255; i >= 0; i--) { int ip = (base & 0xFFFFFF00) | i; @@ -826,6 +927,19 @@ init_ping(void) pi->targets = delete_duplicate_hosts (pi->targets); + if (debug_p) + { + ping_target *t; + fprintf (stderr, "%s: Target list:\n", progname); + for (t = pi->targets; t; t = t->next) + { + struct sockaddr_in *iaddr = (struct sockaddr_in *) &(t->address); + unsigned long ip = iaddr->sin_addr.s_addr; + fprintf (stderr, "%s: ", progname); + print_host (stderr, ip, t->name); + } + } + /* Make sure there is something to ping */ if (pi->targets == NULL) { @@ -1009,6 +1123,8 @@ getping(sonar_info *si, ping_info *pi) char *name; struct sigaction sa; struct itimerval it; + fd_set rfds; + struct timeval tv; /* Set up a signal to interupt our wait for a packet */ @@ -1034,21 +1150,27 @@ getping(sonar_info *si, ping_info *pi) /* Wait for a result packet */ fromlen = sizeof(from); - while (! timer_expired && - (result = recvfrom(pi->icmpsock, packet, sizeof(packet), - 0, &from, &fromlen)) > 0) { + while (! timer_expired) { + tv.tv_usec=pi->timeout; + tv.tv_sec=0; +#if 0 + /* This breaks on BSD, which uses bzero() in the definition of FD_ZERO */ + FD_ZERO(&rfds); +#else + memset (&rfds, 0, sizeof(rfds)); +#endif + FD_SET(pi->icmpsock,&rfds); + /* only wait a little while, in case we raced with the timer expiration. + From Valentijn Sessink */ + if (select(pi->icmpsock+1, &rfds, NULL, NULL, &tv) >0) { + result = recvfrom(pi->icmpsock, packet, sizeof(packet), + 0, &from, &fromlen); /* Check the packet */ gettimeofday(&now, (struct timezone *) 0); ip = (struct ip *) packet; - - iphdrlen = ip->ip_hl << 2; - /* On DEC OSF1 4.0, the preceeding line needs to be - iphdrlen = (ip->ip_vhl & 0x0F) << 2; - but I don't know how to do this portably. -- jwz. - */ - + iphdrlen = IP_HDRLEN(ip) << 2; icmph = (struct ICMP *) &packet[iphdrlen]; /* Was the packet a reply?? */ @@ -1108,6 +1230,7 @@ getping(sonar_info *si, ping_info *pi) new->distance = delta(then, &now) / 100; if (new->distance == 0) new->distance = 2; /* HACK */ + } } /* Done */ @@ -1377,6 +1500,9 @@ init_sonar(Display *dpy, Window win) si->sweep_colors, &si->sweep_segs, False, True, False); + if (si->sweep_segs <= 0) + si->sweep_segs = 1; + /* Done */ return si; @@ -1644,7 +1770,7 @@ Sonar(sonar_info *si, Bogie *bl) /* Check for expired tagets and remove them from the visable list */ prev = NULL; - for (bp = si->visable; bp != NULL; bp = bp->next) { + for (bp = si->visable; bp != NULL; bp = (bp ? bp->next : 0)) { /* * Remove it from the visable list if it's expired or we have @@ -1662,6 +1788,7 @@ Sonar(sonar_info *si, Bogie *bl) else prev->next = bp->next; freeBogie(bp); + bp = prev; } else prev = bp; } @@ -1733,10 +1860,12 @@ parse_mode (Bool ping_works_p) while (token < end) { char *next; +# ifdef HAVE_PING ping_target *new; struct stat st; unsigned int n0=0, n1=0, n2=0, n3=0, m=0; char d; +# endif /* HAVE_PING */ for (next = token; *next != ',' && *next != ' ' && *next != '\t' && *next != '\n'; @@ -1760,6 +1889,7 @@ parse_mode (Bool ping_works_p) return 0; } +#ifdef HAVE_PING if ((4 == sscanf (token, "%d.%d.%d/%d %c", &n0,&n1,&n2, &m,&d)) || (5 == sscanf (token, "%d.%d.%d.%d/%d %c", &n0,&n1,&n2,&n3,&m,&d))) { @@ -1806,6 +1936,7 @@ parse_mode (Bool ping_works_p) sensor = ping; } +#endif /* HAVE_PING */ token = next + 1; while (token < end && @@ -1841,7 +1972,12 @@ screenhack(Display *dpy, Window win) debug_p = get_boolean_resource ("debug", "Debug"); sensor = 0; +# ifdef HAVE_PING sensor_info = (void *) init_ping(); +# else /* !HAVE_PING */ + sensor_info = 0; + parse_mode (0); /* just to check argument syntax */ +# endif /* !HAVE_PING */ if (sensor == 0) {