X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fsonar.c;h=c4169f663dbd362d0a02dc8d492f40fb951d38c9;hb=72c1f4c1dc6ab07fe121a327ff1c30bf51ef74c1;hp=3c492189ad505c093a57f8c46a666768892e9b23;hpb=f65151994eba80ecabcdac6eef6fa0dde7e2d45b;p=xscreensaver diff --git a/hacks/sonar.c b/hacks/sonar.c index 3c492189..c4169f66 100644 --- a/hacks/sonar.c +++ b/hacks/sonar.c @@ -12,11 +12,14 @@ * of bogies that move around on the scope while the ping sensor can be * used to display hosts on your network. * - * The ping code is only compiled in if you define HAVE_PING, because, - * unfortunately, creating an ICMP socket is a privileged operation, the - * program needs to be installed SUID root if you want to use the ping - * mode. If you check the code you will see that this privilige is given up - * immediately after the socket is created. + * The ping code is only compiled in if you define HAVE_ICMP or HAVE_ICMPHDR, + * because, unfortunately, different systems have different ways of creating + * these sorts of packets. + * + * Also: creating an ICMP socket is a privileged operation, so the program + * needs to be installed SUID root if you want to use the ping mode. If you + * check the code you will see that this privilige is given up immediately + * after the socket is created. * * It should be easy to extend this code to support other sorts of sensors. * Some ideas: @@ -25,7 +28,7 @@ * - 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@canada.com). + * Copyright (C) 1998 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 @@ -34,7 +37,7 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * $Revision: 1.6 $ + * $Revision: 1.14 $ * * Version 1.0 April 27, 1998. * - Initial version @@ -72,40 +75,72 @@ * - Now need to define HAVE_PING to compile in the ping stuff. */ +/* These are computed by configure now: + #define HAVE_ICMP + #define HAVE_ICMPHDR + */ + + /* Include Files */ -#ifdef HAVE_PING -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif /* HAVE_PING */ -#include -#include #include +#include +#include + #include "screenhack.h" #include "colors.h" #include "hsv.h" -#include + +#if defined(HAVE_ICMP) || defined(HAVE_ICMPHDR) +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif /* HAVE_ICMP || HAVE_ICMPHDR */ + /* Defines */ -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a - 50):(b - 10)) -#endif /* MIN */ +#undef MY_MIN +#define MY_MIN(a,b) ((a)<(b)?(a - 50):(b - 10)) + +#ifndef LINE_MAX +# define LINE_MAX 2048 +#endif + +/* Frigging icmp */ + +#if defined(HAVE_ICMP) +# define HAVE_PING +# define ICMP icmp +# define ICMP_TYPE(p) (p)->icmp_type +# define ICMP_CODE(p) (p)->icmp_code +# define ICMP_CHECKSUM(p) (p)->icmp_cksum +# define ICMP_ID(p) (p)->icmp_id +# define ICMP_SEQ(p) (p)->icmp_seq +#elif defined(HAVE_ICMPHDR) +# define HAVE_PING +# define ICMP icmphdr +# define ICMP_TYPE(p) (p)->type +# define ICMP_CODE(p) (p)->code +# define ICMP_CHECKSUM(p) (p)->checksum +# define ICMP_ID(p) (p)->un.echo.id +# define ICMP_SEQ(p) (p)->un.echo.sequence +#else +# undef HAVE_PING +#endif /* Forward References */ @@ -157,7 +192,7 @@ typedef struct { centrex, centrey, radius; /* Parts of the scope circle */ Bogie *visable; /* List of visable objects */ int current; /* Current position of sweep */ - + int sweepnum; /* The current id of the sweep */ int delay; /* how long between each frame of the anim */ } sonar_info; @@ -199,7 +234,6 @@ typedef struct { static int timer_expired; - #endif /* HAVE_PING */ /* @@ -210,7 +244,7 @@ typedef struct sim_target { char *name; /* The name of the target */ int nexttick; /* The next tick that this will be seen */ int nextdist; /* The distance on that tick */ - int movedlasttick; /* Flag to indicate we just moved this one */ + int movedonsweep; /* The number of the sweep this last moved */ } sim_target; /* @@ -317,7 +351,7 @@ newBogie(char *name, int distance, int tick, int ttl) /* Allocate a bogie and initialize it */ if ((new = (Bogie *) calloc(1, sizeof(Bogie))) == NULL) { - fprintf(stderr, "Out of Memory\n"); + fprintf(stderr, "%s: Out of Memory\n", progname); return NULL; } new->name = name; @@ -415,7 +449,8 @@ lookupHost(ping_target *target) struct hostent *hent = gethostbyname(target->name); if (hent == NULL) { - fprintf(stderr, "Could not resolve host %s\n", target->name); + fprintf(stderr, "%s: could not resolve host %s\n", + progname, target->name); return 0; } memcpy(&iaddr->sin_addr, hent->h_addr_list[0], @@ -448,11 +483,11 @@ newHost(char *name) /* Create the target */ if ((target = calloc(1, sizeof(ping_target))) == NULL) { - fprintf(stderr, "Out of Memory\n"); + fprintf(stderr, "%s: Out of Memory\n", progname); goto target_init_error; } if ((target->name = strdup(name)) == NULL) { - fprintf(stderr, "Out of Memory\n"); + fprintf(stderr, "%s: Out of Memory\n", progname); goto target_init_error; } @@ -500,7 +535,7 @@ readPingHostsFile(char *fname) /* Make sure we in fact have a file to process */ if ((fname == NULL) || (fname[0] == '\0')) { - fprintf(stderr, "Invalid ping host file name\n"); + fprintf(stderr, "%s: invalid ping host file name\n", progname); return NULL; } @@ -508,7 +543,7 @@ readPingHostsFile(char *fname) if ((fp = fopen(fname, "r")) == NULL) { char msg[1024]; - sprintf(msg, "Unable to open host file %s", fname); + sprintf(msg, "%s: unable to open host file %s", progname, fname); perror(msg); return NULL; } @@ -537,12 +572,28 @@ readPingHostsFile(char *fname) else continue; + /* Check to see if the addr looks like an addr. If not, assume + the addr is a name and there is no addr. This way, we can + handle files whose lines have "xx.xx.xx.xx hostname" as their + first two tokens, and also files that have a hostname as their + first token (like .ssh/known_hosts and .rhosts.) + */ + { + int i; char c; + if (4 != sscanf(addr, "%d.%d.%d.%d%c", &i, &i, &i, &i, &c)) + { + name = addr; + addr = NULL; + } + } + /*printf ("\"%s\" \"%s\"\n", name, addr);*/ + /* Create a new target using first the name then the address */ new = NULL; if (name != NULL) new = newHost(name); - if (new == NULL) + if (new == NULL && addr != NULL) new = newHost(addr); /* Add it to the list if we got one */ @@ -626,14 +677,14 @@ subnetHostsList(void) /* Get our hostname */ if (gethostname(hostname, BUFSIZ)) { - fprintf(stderr, "Unable to get local hostname\n"); + fprintf(stderr, "%s: unable to get local hostname\n", progname); return NULL; } /* Get our IP address and convert it to a string */ if ((hent = gethostbyname(hostname)) == NULL) { - fprintf(stderr, "Unable to lookup our IP address\n"); + fprintf(stderr, "%s: unable to lookup our IP address\n", progname); return NULL; } strcpy(address, inet_ntoa(*((struct in_addr *)hent->h_addr_list[0]))); @@ -641,13 +692,17 @@ subnetHostsList(void) /* Get a pointer to the last "." in the string */ if ((p = strrchr(address, '.')) == NULL) { - fprintf(stderr, "Can't parse IP address %s\n", address); + fprintf(stderr, "%s: can't parse IP address %s\n", progname, address); return NULL; } p++; /* Construct targets for all addresses in this subnet */ + /* #### jwz: actually, this is wrong, since it assumes a + netmask of 255.255.255.0. But I'm not sure how to find + the local netmask. + */ for (i = 254; i > 0; i--) { sprintf(p, "%d", i); new = newHost(address); @@ -682,14 +737,16 @@ init_ping(void) /* Create the ping info structure */ if ((pi = (ping_info *) calloc(1, sizeof(ping_info))) == NULL) { - fprintf(stderr, "Out of memory\n"); + fprintf(stderr, "%s: Out of memory\n", progname); goto ping_init_error; } /* Create the ICMP socket and turn off SUID */ if ((pi->icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { - perror("Can't create ICMP socket"); + char msg[1024]; + sprintf(msg, "%s: can't create ICMP socket", progname); + perror(msg); fprintf(stderr, "%s: this program must be setuid to root for `ping mode' to work.\n", progname); @@ -728,14 +785,16 @@ init_ping(void) /* Unknown source */ - fprintf(stderr, "Illegal pingSource: %s\n", src); - goto ping_init_error; + fprintf(stderr, + "%s: pingSource must be `file', `list', or `subnet', not: %s\n", + progname, src); + exit (1); } /* Make sure there is something to ping */ if (pi->targets == NULL) { - fprintf(stderr, "Nothing to ping"); + fprintf(stderr, "%s: nothing to ping", progname); goto ping_init_error; } @@ -775,7 +834,7 @@ sendping(ping_info *pi, ping_target *pt) /* Local Variables */ u_char *packet; - struct icmp *icmph; + struct ICMP *icmph; int result; /* @@ -784,24 +843,24 @@ sendping(ping_info *pi, ping_target *pt) * name or do an address lookup when it comes back. */ - int pcktsiz = sizeof(struct icmp) + sizeof(struct timeval) + + int pcktsiz = sizeof(struct ICMP) + sizeof(struct timeval) + strlen(pt->name) + 1; /* Create the ICMP packet */ if ((packet = (u_char *) malloc(pcktsiz)) == (void *) 0) return; /* Out of memory */ - icmph = (struct icmp *) packet; - icmph->icmp_type = ICMP_ECHO; - icmph->icmp_code = 0; - icmph->icmp_cksum = 0; - icmph->icmp_id = pi->pid; - icmph->icmp_seq = pi->seq++; - gettimeofday((struct timeval *) &packet[sizeof(struct icmp)], + icmph = (struct ICMP *) packet; + ICMP_TYPE(icmph) = ICMP_ECHO; + ICMP_CODE(icmph) = 0; + ICMP_CHECKSUM(icmph) = 0; + ICMP_ID(icmph) = pi->pid; + ICMP_SEQ(icmph) = pi->seq++; + gettimeofday((struct timeval *) &packet[sizeof(struct ICMP)], (struct timezone *) 0); - strcpy((char *) &packet[sizeof(struct icmp) + sizeof(struct timeval)], + strcpy((char *) &packet[sizeof(struct ICMP) + sizeof(struct timeval)], pt->name); - icmph->icmp_cksum = checksum((u_short *)packet, pcktsiz); + ICMP_CHECKSUM(icmph) = checksum((u_short *)packet, pcktsiz); /* Send it */ @@ -809,7 +868,7 @@ sendping(ping_info *pi, ping_target *pt) &pt->address, sizeof(pt->address))) != pcktsiz) { #if 0 char errbuf[BUFSIZ]; - sprintf(errbuf, "Error sending ping to %s", pt->name); + sprintf(errbuf, "%s: error sending ping to %s", progname, pt->name); perror(errbuf); #endif } @@ -866,6 +925,7 @@ checksum(u_short *packet, int size) if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; + *(1 + (u_char *)(&answer)) = 0; sum += answer; } @@ -908,7 +968,7 @@ getping(sonar_info *si, ping_info *pi, int ttl) struct timeval *then; struct ip *ip; int iphdrlen; - struct icmp *icmph; + struct ICMP *icmph; Bogie *bl = NULL; Bogie *new; char *name; @@ -921,7 +981,9 @@ getping(sonar_info *si, ping_info *pi, int ttl) sa.sa_flags = 0; sa.sa_handler = sigcatcher; if (sigaction(SIGALRM, &sa, 0) == -1) { - perror("Unable to trap sigalarm"); + char msg[1024]; + sprintf(msg, "%s: unable to trap SIGALRM", progname); + perror(msg); exit(1); } @@ -945,19 +1007,25 @@ getping(sonar_info *si, ping_info *pi, int ttl) gettimeofday(&now, (struct timezone *) 0); ip = (struct ip *) packet; + iphdrlen = ip->ip_hl << 2; - icmph = (struct icmp *) &packet[iphdrlen]; + /* 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. + */ + + icmph = (struct ICMP *) &packet[iphdrlen]; /* Was the packet a reply?? */ - if (icmph->icmp_type != ICMP_ECHOREPLY) { + if (ICMP_TYPE(icmph) != ICMP_ECHOREPLY) { /* Ignore anything but ICMP Replies */ continue; /* Nope */ } /* Was it for us? */ - if (icmph->icmp_id != pi->pid) { + if (ICMP_ID(icmph) != pi->pid) { /* Ignore packets not set from us */ continue; /* Nope */ } @@ -966,9 +1034,9 @@ getping(sonar_info *si, ping_info *pi, int ttl) if ((name = strdup((char *) &packet[iphdrlen + - + sizeof(struct icmp) + + sizeof(struct ICMP) + sizeof(struct timeval)])) == NULL) { - fprintf(stderr, "Out of memory\n"); + fprintf(stderr, "%s: Out of memory\n", progname); return bl; } @@ -1001,7 +1069,7 @@ getping(sonar_info *si, ping_info *pi, int ttl) /* Compute the round trip time */ then = (struct timeval *) &packet[iphdrlen + - sizeof(struct icmp)]; + sizeof(struct ICMP)]; new->distance = delta(then, &now) / 100; if (new->distance == 0) new->distance = 2; /* HACK */ @@ -1027,6 +1095,11 @@ static Bogie * ping(sonar_info *si, void *vpi) { + /* + * This tries to distribute the targets evely around the field of the + * sonar. + */ + ping_info *pi = (ping_info *) vpi; static ping_target *ptr = NULL; @@ -1088,14 +1161,10 @@ init_sim(void) sim_info *si; int i; - /* Seed the random number generator */ - - srand((int) time(NULL)); - /* Create the simulation info structure */ if ((si = (sim_info *) calloc(1, sizeof(sim_info))) == NULL) { - fprintf(stderr, "Out of memory\n"); + fprintf(stderr, "%s: Out of memory\n", progname); return NULL; } @@ -1105,7 +1174,7 @@ init_sim(void) if ((si->teamA = (sim_target *)calloc(si->numA, sizeof(sim_target))) == NULL) { free(si); - fprintf(stderr, "Out of Memory\n"); + fprintf(stderr, "%s: Out of Memory\n", progname); return NULL; } si->teamAID = get_string_resource("teamAName", "TeamAName"); @@ -1113,12 +1182,13 @@ init_sim(void) if ((si->teamA[i].name = (char *) malloc(strlen(si->teamAID) + 4)) == NULL) { free(si); - fprintf(stderr, "Out of Memory\n"); + fprintf(stderr, "%s: Out of Memory\n", progname); return NULL; } sprintf(si->teamA[i].name, "%s%03d", si->teamAID, i+1); - si->teamA[i].nexttick = (int) (90.0 * rand() / RAND_MAX); - si->teamA[i].nextdist = (int) (100.0 * rand() / RAND_MAX); + si->teamA[i].nexttick = (int) (90.0 * random() / RAND_MAX); + si->teamA[i].nextdist = (int) (100.0 * random() / RAND_MAX); + si->teamA[i].movedonsweep = -1; } /* Team B */ @@ -1127,7 +1197,7 @@ init_sim(void) if ((si->teamB = (sim_target *)calloc(si->numB, sizeof(sim_target))) == NULL) { free(si); - fprintf(stderr, "Out of Memory\n"); + fprintf(stderr, "%s: Out of Memory\n", progname); return NULL; } si->teamBID = get_string_resource("teamBName", "TeamBName"); @@ -1135,12 +1205,13 @@ init_sim(void) if ((si->teamB[i].name = (char *) malloc(strlen(si->teamBID) + 4)) == NULL) { free(si); - fprintf(stderr, "Out of Memory\n"); + fprintf(stderr, "%s: Out of Memory\n", progname); return NULL; } sprintf(si->teamB[i].name, "%s%03d", si->teamBID, i+1); - si->teamB[i].nexttick = (int) (90.0 * rand() / RAND_MAX); - si->teamB[i].nextdist = (int) (100.0 * rand() / RAND_MAX); + si->teamB[i].nexttick = (int) (90.0 * random() / RAND_MAX); + si->teamB[i].nextdist = (int) (100.0 * random() / RAND_MAX); + si->teamB[i].movedonsweep = -1; } /* Done */ @@ -1175,7 +1246,7 @@ init_sonar(Display *dpy, Window win) /* Create the Sonar information structure */ if ((si = (sonar_info *) calloc(1, sizeof(sonar_info))) == NULL) { - fprintf(stderr, "Out of memory\n"); + fprintf(stderr, "%s: Out of memory\n", progname); return NULL; } @@ -1190,19 +1261,20 @@ init_sonar(Display *dpy, Window win) si->height = xwa.height; si->centrex = si->width / 2; si->centrey = si->height / 2; - si->maxx = si->centrex + MIN(si->centrex, si->centrey) - 10; - si->minx = si->centrex - MIN(si->centrex, si->centrey) + 10; - si->maxy = si->centrey + MIN(si->centrex, si->centrey) - 10; - si->miny = si->centrey - MIN(si->centrex, si->centrey) + 10; + si->maxx = si->centrex + MY_MIN(si->centrex, si->centrey) - 10; + si->minx = si->centrex - MY_MIN(si->centrex, si->centrey) + 10; + si->maxy = si->centrey + MY_MIN(si->centrex, si->centrey) - 10; + si->miny = si->centrey - MY_MIN(si->centrex, si->centrey) + 10; si->radius = si->maxx - si->centrex; si->current = 0; + si->sweepnum = 0; /* Get the font */ if (((si->font = XLoadQueryFont(dpy, get_string_resource ("font", "Font"))) == NULL) && ((si->font = XLoadQueryFont(dpy, "fixed")) == NULL)) { - fprintf(stderr, "Can't load an appropriate font\n"); + fprintf(stderr, "%s: can't load an appropriate font\n", progname); return NULL; } @@ -1283,9 +1355,8 @@ updateLocation(sim_target *t) int xdist, xtick; - t->movedlasttick = 1; - xtick = (int) (3.0 * rand() / RAND_MAX) - 1; - xdist = (int) (11.0 * rand() / RAND_MAX) - 5; + xtick = (int) (3.0 * random() / RAND_MAX) - 1; + xdist = (int) (11.0 * random() / RAND_MAX) - 5; if (((t->nexttick + xtick) < 90) && ((t->nexttick + xtick) >= 0)) t->nexttick += xtick; else @@ -1322,29 +1393,30 @@ simulator(sonar_info *si, void *vinfo) for (i = 0; i < info->numA; i++) { t = &info->teamA[i]; - if (!t->movedlasttick && (t->nexttick == (si->current * -1))) { + if ((t->movedonsweep != si->sweepnum) && + (t->nexttick == (si->current * -1))) { new = newBogie(strdup(t->name), t->nextdist, si->current, TTL); if (list != NULL) new->next = list; list = new; updateLocation(t); - } else - t->movedlasttick = 0; + t->movedonsweep = si->sweepnum; + } } /* Team B */ for (i = 0; i < info->numB; i++) { t = &info->teamB[i]; - if (!t->movedlasttick && (t->nexttick == (si->current * -1))) { + if ((t->movedonsweep != si->sweepnum) && + (t->nexttick == (si->current * -1))) { new = newBogie(strdup(t->name), t->nextdist, si->current, TTL); if (list != NULL) new->next = list; list = new; - t->movedlasttick = 1; updateLocation(t); - } else - t->movedlasttick = 0; + t->movedonsweep = si->sweepnum; + } } /* Done */ @@ -1421,7 +1493,8 @@ DrawBogie(sonar_info *si, int draw, char *name, int degrees, /* Compute the coordinates of the object */ - distance = (log((double) distance) / 10.0) * si->radius; + if (distance != 0) + distance = (log((double) distance) / 10.0) * si->radius; x = ox + ((double) distance * cos(4.0 * ((double) degrees)/57.29578)); y = oy - ((double) distance * sin(4.0 * ((double) degrees)/57.29578)); @@ -1654,7 +1727,7 @@ screenhack(Display *dpy, Window win) if ((sensor_info = (void *) init_sim()) == NULL) exit(1); } else { - fprintf(stderr, "Unsupported Sonar mode: %s\n", mode); + fprintf(stderr, "%s: unsupported Sonar mode: %s\n", progname, mode); fprintf(stderr, "\tCurrently supported modes are `ping' and `simulation'\n"); exit(1); @@ -1677,11 +1750,14 @@ screenhack(Display *dpy, Window win) /* Set up and sleep for the next one */ si->current = (si->current - 1) % 90; + if (si->current == 0) + si->sweepnum++; XSync (dpy, False); gettimeofday(&finish, (struct timezone *) 0); sleeptime = si->delay - delta(&start, &finish); screenhack_handle_events (dpy); if (sleeptime > 0L) usleep(sleeptime); + } }