* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
- * $Revision: 1.32 $
+ * $Revision: 1.39 $
*
* Version 1.0 April 27, 1998.
* - Initial version
typedef struct Bogie {
char *name; /* The name of the thing being displayed */
+ char *desc; /* Beneath the name (e.g., ping time) */
int distance; /* The distance to this thing (0 - 100) */
int tick; /* The tick that it was found on */
int ttl; /* The time to live */
} sonar_info;
static Bool debug_p = False;
+static Bool resolve_p = True;
+static Bool times_p = True;
/*
"*teamBCount: 4",
"*ping: default",
+ "*resolve: true",
+ "*showTimes: true",
".debug: false",
0
};
{"-team-b-count", ".teamBCount", XrmoptionSepArg, 0 },
{"-ping", ".ping", XrmoptionSepArg, 0 },
+ {"-no-dns", ".resolve", XrmoptionNoArg, "False" },
+ {"-no-times", ".showTimes", XrmoptionNoArg, "False" },
{"-debug", ".debug", XrmoptionNoArg, "True" },
{ 0, 0, 0, 0 }
};
}
iaddr->sin_addr.s_addr = pack_addr (ip[0], ip[1], ip[2], ip[3]);
- hent = gethostbyaddr ((const char *) &iaddr->sin_addr.s_addr,
- sizeof(iaddr->sin_addr.s_addr),
- AF_INET);
+ if (resolve_p)
+ hent = gethostbyaddr ((const char *) &iaddr->sin_addr.s_addr,
+ sizeof(iaddr->sin_addr.s_addr),
+ AF_INET);
+ else
+ hent = 0;
if (debug_p > 1)
fprintf (stderr, "%s: %s => %s\n",
hent = gethostbyname (target->name);
if (!hent)
{
- fprintf (stderr, "%s: could not resolve host: %s\n",
- progname, target->name);
+ if (debug_p)
+ fprintf (stderr, "%s: could not resolve host: %s\n",
+ progname, target->name);
return 0;
}
struct sockaddr_in *iaddr = (struct sockaddr_in *) &(target->address);
unsigned long ip = iaddr->sin_addr.s_addr;
- if ((ntohl (ip) & 0xFFFFFF00L) == 0x7f000000L) /* 127.0.0 */
+ if ((ntohl (ip) & 0xFFFFFF00L) == 0x7f000000L) /* 127.0.0.x */
{
if (debug_p)
fprintf (stderr, "%s: ignoring loopback host %s\n",
}
}
+ /* Don't ever use broadcast (255.x.x.x) hosts */
+ {
+ struct sockaddr_in *iaddr = (struct sockaddr_in *) &(target->address);
+ unsigned long ip = iaddr->sin_addr.s_addr;
+ if ((ntohl (ip) & 0xFF000000L) == 0xFF000000L) /* 255.x.x.x */
+ {
+ if (debug_p)
+ fprintf (stderr, "%s: ignoring broadcast host %s\n",
+ progname, target->name);
+ goto target_init_error;
+ }
+ }
+
/* Done */
if (debug_p)
goto ping_init_error;
}
- /* Create the ICMP socket */
+ /* Create the ICMP socket. Do this before dropping privs.
- if ((pi->icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) >= 0) {
+ Raw sockets can only be opened by root (or setuid root), so we
+ only try to do this when the effective uid is 0.
+
+ We used to just always try, and notice the failure. But apparently
+ that causes "SELinux" to log spurious warnings when running with the
+ "strict" policy. So to avoid that, we just don't try unless we
+ know it will work.
+ */
+ if (geteuid() == 0 &&
+ (pi->icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) >= 0) {
socket_initted_p = True;
}
ip = (struct ip *) packet;
iphdrlen = IP_HDRLEN(ip) << 2;
icmph = (struct ICMP *) &packet[iphdrlen];
+ then = (struct timeval *) &packet[iphdrlen + sizeof(struct ICMP)];
+
/* Was the packet a reply?? */
return bl;
}
+# if 0 /* Don't need to do this -- the host names are already as
+ resolved as they're going to get. (We stored the resolved
+ name in the outgoing ping packet, so that same string just
+ came back to us.)
+ */
+
/* If the name is an IP addr, try to resolve it. */
{
int iip[4];
struct sockaddr_in iaddr;
struct hostent *h;
iaddr.sin_addr.s_addr = pack_addr (iip[0],iip[1],iip[2],iip[3]);
- h = gethostbyaddr ((const char *) &iaddr.sin_addr.s_addr,
- sizeof(iaddr.sin_addr.s_addr),
- AF_INET);
+ if (resolve_p)
+ h = gethostbyaddr ((const char *) &iaddr.sin_addr.s_addr,
+ sizeof(iaddr.sin_addr.s_addr),
+ AF_INET);
+ else
+ h = 0;
if (h && h->h_name && *h->h_name)
{
}
}
}
+# endif /* 0 */
/* Create the new Bogie and add it to the list we are building */
new->next = bl;
bl = new;
- /* Compute the round trip time */
+ {
+ float msec = delta(then, &now) / 1000.0;
+
+ if (times_p)
+ {
+ if (new->desc) free (new->desc);
+ new->desc = (char *) malloc (30);
+ if (msec > 99) sprintf (new->desc, " %.0f ms ", msec);
+ else if (msec > 9) sprintf (new->desc, " %.1f ms ", msec);
+ else if (msec > 1) sprintf (new->desc, " %.2f ms ", msec);
+ else sprintf (new->desc, " %.3f ms ", msec);
+ }
+
+ if (debug_p && times_p) /* print ping-like stuff to stdout */
+ {
+ struct sockaddr_in *iaddr = (struct sockaddr_in *) &from;
+ unsigned int a, b, c, d;
+ char ipstr[20];
+ char *s = strdup (new->desc);
+ char *s2 = s, *s3 = s;
+ while (*s2 == ' ') s2++;
+ s3 = strchr (s2, ' ');
+ if (s3) *s3 = 0;
+
+ unpack_addr (iaddr->sin_addr.s_addr, &a, &b, &c, &d);
+ sprintf (ipstr, "%d.%d.%d.%d", a, b, c, d);
+
+ fprintf (stdout,
+ "%3d bytes from %28s: "
+ "icmp_seq=%-4d ttl=%d time=%s ms\n",
+ result,
+ name,
+ /*ipstr,*/
+ ICMP_SEQ(icmph), si->TTL, s2);
+ free (s);
+ }
+
+ /* Don't put anyone *too* close to the center of the screen. */
+ msec += 0.6;
- then = (struct timeval *) &packet[iphdrlen +
- sizeof(struct ICMP)];
- new->distance = delta(then, &now) / 100;
- if (new->distance == 0)
- new->distance = 2; /* HACK */
+ new->distance = msec * 10;
+ }
}
}
}
+static void
+reshape (sonar_info *si)
+{
+ XWindowAttributes xgwa;
+ Pixmap mask;
+ XGetWindowAttributes(si->dpy, si->win, &xgwa);
+ si->width = xgwa.width;
+ si->height = xgwa.height;
+ si->centrex = si->width / 2;
+ si->centrey = si->height / 2;
+ 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;
+
+ /* Install the clip mask... */
+ mask = scope_mask (si->dpy, si->win, si);
+ XSetClipMask(si->dpy, si->text, mask);
+ XSetClipMask(si->dpy, si->erase, mask);
+ XFreePixmap (si->dpy, mask); /* it's been copied into the GCs */
+}
+
/*
* Initialize the Sonar.
*
si->dpy = dpy;
si->win = win;
si->visible = NULL;
+
XGetWindowAttributes(dpy, win, &xwa);
si->cmap = xwa.colormap;
- si->width = xwa.width;
- si->height = xwa.height;
- si->centrex = si->width / 2;
- si->centrey = si->height / 2;
- 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;
dpy, si->cmap);
si->grid = XCreateGC (dpy, win, GCForeground, &gcv);
- /* Install the clip mask... */
- {
- Pixmap mask = scope_mask (dpy, win, si);
- XSetClipMask(dpy, si->text, mask);
- XSetClipMask(dpy, si->erase, mask);
- XFreePixmap (dpy, mask); /* it's been copied into the GCs */
- }
+ reshape (si);
/* Compute pixel values for fading text on the display */
*/
static int
-computeStringX(sonar_info *si, char *label, int x)
+computeStringX(sonar_info *si, const char *label, int x)
{
int width = XTextWidth(si->font, label, strlen(label));
* The y coordinate of the start of the label.
*/
-/* TODO: Add smarts to keep label in sonar screen */
-
static int
computeStringY(sonar_info *si, int y)
{
- int fheight = si->font->ascent + si->font->descent;
- return y + 5 + fheight;
+ int fheight = si->font->ascent /* + si->font->descent */;
+ return y + fheight;
}
/*
*/
static void
-DrawBogie(sonar_info *si, int draw, char *name, int degrees,
- int distance, int ttl, int age)
+DrawBogie(sonar_info *si, int draw, const char *name, const char *desc,
+ int degrees, int distance, int ttl, int age)
{
/* Local Variables */
/* Draw (or erase) the Bogie */
XFillArc(si->dpy, si->win, gc, x, y, 5, 5, 0, 360 * 64);
+
+ x += 3; /* move away from the dot */
+ y += 7;
+ y = computeStringY(si, y);
XDrawString(si->dpy, si->win, gc,
- computeStringX(si, name, x),
- computeStringY(si, y), name, strlen(name));
+ computeStringX(si, name, x), y,
+ name, strlen(name));
+
+ if (desc && *desc)
+ {
+ y = computeStringY(si, y);
+ XDrawString(si->dpy, si->win, gc,
+ computeStringX(si, desc, x), y,
+ desc, strlen(desc));
+ }
}
if (((bp->tick == si->current) && (++bp->age >= bp->ttl)) ||
(findNode(bl, bp->name) != NULL)) {
- DrawBogie(si, 0, bp->name, bp->tick,
+ DrawBogie(si, 0, bp->name, bp->desc, bp->tick,
bp->distance, bp->ttl, bp->age);
if (prev == NULL)
si->visible = bp->next;
for (bp = si->visible; bp != NULL; bp = bp->next) {
if (bp->age < bp->ttl) /* grins */
- DrawBogie(si, 1, bp->name, bp->tick, bp->distance, bp->ttl,bp->age);
+ DrawBogie(si, 1, bp->name, bp->desc,
+ bp->tick, bp->distance, bp->ttl,bp->age);
}
/* Redraw the grid */
}
+static void
+handle_events (sonar_info *si)
+{
+ while (XPending (si->dpy))
+ {
+ XEvent event;
+ XNextEvent (si->dpy, &event);
+
+ if (event.xany.type == ConfigureNotify)
+ {
+ XClearWindow (si->dpy, si->win);
+ reshape (si);
+ }
+
+ screenhack_handle_event (si->dpy, &event);
+ }
+}
+
+
/*
* Main screen saver hack.
long sleeptime;
debug_p = get_boolean_resource ("debug", "Debug");
+ resolve_p = get_boolean_resource ("resolve", "Resolve");
+ times_p = get_boolean_resource ("showTimes", "ShowTimes");
sensor = 0;
# ifdef HAVE_PING
gettimeofday(&finish);
# endif
sleeptime = si->delay - delta(&start, &finish);
- screenhack_handle_events (dpy);
+ handle_events (si);
if (sleeptime > 0L)
usleep(sleeptime);