|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T x
Length: 18393 (0x47d9) Types: TextFile Names: »xface.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/others/image/xface.c«
/* xface.c - face agent for X windows */ #ifndef lint static char *rcsid = "$Header: /f/osi/others/image/RCS/xface.c,v 6.0 89/03/18 23:35:21 mrose Rel $"; #endif /* * $Header: /f/osi/others/image/RCS/xface.c,v 6.0 89/03/18 23:35:21 mrose Rel $ * * * $Log: xface.c,v $ * Revision 6.0 89/03/18 23:35:21 mrose * Release 5.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ #include <errno.h> #include <stdio.h> #include "imagesbr.h" #include <isode/internet.h> #include <isode/logger.h> #include <X11/Xlib.h> #include <X11/Xutil.h> /* \f DATA */ static int sd = NOTOK; int debug = 0; int errsw = 0; static int portsw = 0; static int ppidsw = 0; static int sleepsw = 30; char *myname = "xface"; static char *prefix = "faces"; static int eventfd = NOTOK; static int (*eventfx)() = NULL; static int (*alarmfx)() = NULL; struct aka { struct aka *ak_forw; struct aka *ak_back; char *ak_host; char *ak_user; int ak_flags; #define AK_NULL 0x00 #define AK_HWL 0x01 #define AK_HWR 0x02 #define AK_UWL 0x04 #define AK_UWR 0x08 #define AK_WILD (AK_HWL | AK_HWR | AK_UWL | AK_UWR) #define AK_INV 0x10 #define AK_MASK "\020\01HWL\02HWR\03UWL\04UWR\05INV" char *ak_template; struct type_IMAGE_Image *ak_image; }; static struct aka akas; static struct aka *AHead = &akas; static int recording = 0; static LLog _pgm_log = { "./image.log", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK }; LLog *pgm_log = &_pgm_log; static char *display = NULL; static char *geometry = NULL; static Display *DISP; static int SCRN; static struct type_IMAGE_Image *myim = NULL; typedef struct _frame { short x, y; unsigned int width, height; unsigned int bdrwidth; unsigned long border; unsigned long background; } Frame; static int mapped; static int parent; static Window mywindow = 0; static Frame myframe; static unsigned long backpix, bdrpix; static GC forepix, highpix; int ALRMser (), XWINser (); extern int errno; char *getenv (); /* \f MAIN */ /* ARGSUSED */ main (argc, argv, envp) int argc; char **argv, **envp; { char buffer[BUFSIZ], *vec[NVEC + 1]; arginit (argc, argv); if (portsw > 0) startsocket (portsw); if (ppidsw > 0) envinit (); if (errsw) errsw = NOTOK; for (;;) { if ((portsw > 0 ? readsocket (buffer) : getline (buffer)) == NOTOK) break; if (str2vec (buffer, vec) < 2) continue; if (strcmp (vec[0], "addr") == 0) /* temporary... */ fetch_face (vec[1], vec[2]); /* for backwards compat */ else /* .. */ fetch_face (vec[0], vec[1]); if (debug) (void) fflush (stderr); } exit (0); } /* \f */ static fetch_face (host, user) char *host, *user; { char hmatch[BUFSIZ], umatch[BUFSIZ]; register struct aka *ak; if (recording) LLOG (pgm_log, LLOG_NOTICE, ("trying \"%s\" \"%s\"", host, user)); for (ak = AHead -> ak_forw; ak != AHead; ak = ak -> ak_forw) { register int i, j; if (debug) fprintf (stderr, "check \"%s\" \"%s\" %s\n", ak -> ak_host, ak -> ak_user, sprintb (ak -> ak_flags, AK_MASK)); #define do_field(field,element,left,right,match) \ switch (ak -> ak_flags & (left | right)) { \ case AK_NULL: \ default: \ if (strcmp (field, element)) \ continue; \ (void) strcpy (match, field); \ break; \ \ case left: \ i = strlen (field), j = strlen (element); \ if (i < j || strncmp (field + (i - j), element, j)) \ continue; \ (void) strncpy (match, field, i - j); \ break; \ \ case right: \ i = strlen (field), j = strlen (element); \ if (i < j || strncmp (field, element, j)) \ continue; \ (void) strncpy (match, field + j, i - j); \ break; \ \ case left | right: \ if ((j = strlen (element)) > 0) { \ for (i = strlen (field) - j; i >= 0; i--) \ if (strncmp (field + i, element, j) == 0) \ break; \ if (i < 0) \ continue; \ } \ (void) strcpy (match, field); \ break; \ } do_field (host, ak -> ak_host, AK_HWL, AK_HWR, hmatch); do_field (user, ak -> ak_user, AK_UWL, AK_UWR, umatch); #undef do_field if (debug) fprintf (stderr, "%s hit\n", ak -> ak_flags & AK_WILD ? "wild" : "exact"); break; } if (ak == AHead) adios (NULLCP, "internal error"); if (ak -> ak_flags & AK_WILD) { register char *bp, *cp, *dp; char name[BUFSIZ]; register struct aka *am; if ((am = (struct aka *) calloc (1, sizeof *am)) == NULL || (am -> ak_host = strdup (host)) == NULL || (am -> ak_user = strdup (user)) == NULL) adios (NULLCP, "out of memory"); am -> ak_flags = ak -> ak_flags & ~AK_WILD; bp = name; for (cp = ak -> ak_template; *cp; cp++) if (*cp != '$') *bp++ = *cp; else switch (*++cp) { case '$': *bp++ = '$'; break; case 'a': if ((dp = alias2name (host)) == NULL) dp = host; (void) strcpy (bp, dp); bp += strlen (bp); break; case 'A': if ((dp = alias2name (hmatch)) == NULL) dp = hmatch; (void) strcpy (bp, dp); bp += strlen (bp); break; case 'h': (void) strcpy (bp, host); bp += strlen (bp); break; case 'H': (void) strcpy (bp, hmatch); bp += strlen (bp); break; case 'u': (void) strcpy (bp, user); bp += strlen (bp); break; case 'U': (void) strcpy (bp, umatch); bp += strlen (bp); break; default: *bp++ = '$', *bp++ = *cp; } *bp = NULL; if (recording && ak -> ak_forw == AHead) LLOG (pgm_log, LLOG_NOTICE, ("miss \"%s\" \"%s\" \"%s\"", host, user, name)); if ((am -> ak_template = strdup (name)) == NULL) adios (NULLCP, "out of memory"); insque (ak = am, AHead); } if (ak -> ak_image == NULL) { if (!(ak -> ak_flags & AK_INV)) { ak -> ak_image = fetch_image (ak -> ak_template); if (recording && ak -> ak_image == NULL) LLOG (pgm_log, LLOG_NOTICE, ("no image for \"%s\"", ak -> ak_template)); } } else if (debug) fprintf (stderr, "using cached image\n"); myim = ak -> ak_image; if (mywindow != NULL || myim) display_X (); } /* \f */ static int getline (buffer) char *buffer; { register int i; register char *cp, *ep; static int sticky = 0; if (sticky) { sticky = 0; return NOTOK; } printf ("%s> ", myname); (void) fflush (stdout); for (ep = (cp = buffer) + BUFSIZ - 1; (i = getchar ()) != '\n';) { if (i == EOF) { printf ("\n"); if (cp != buffer) { sticky++; break; } return NOTOK; } if (cp < ep) *cp++ = i; } *cp = NULL; return OK; } /* \f */ static init_aka () { int vecp; char *cp, buffer[BUFSIZ], file[BUFSIZ], *vec[NVEC + 1]; register struct aka *ak; FILE *fp; AHead -> ak_forw = AHead -> ak_back = AHead; if ((cp = getenv ("HOME")) == NULL) cp = "."; (void) sprintf (file, "%s/.%s_mappings", cp, myname); if (fp = fopen (file, "r")) { while (fgets (buffer, sizeof buffer, fp)) { if (*buffer == '#') continue; if (cp = index (buffer, '\n')) *cp = NULL; if (*buffer == NULL) continue; if ((vecp = str2vec (buffer, vec)) < 2 || vecp > 3) adios (NULLCP, "%s: invalid line \"%s\"", file, buffer); if ((ak = (struct aka *) calloc (1, sizeof *ak)) == NULL) adios (NULLCP, "out of memory"); #define do_field(field,element,left,right) \ element = *field == '*' ? (ak -> ak_flags |= left, field + 1) \ : field; \ if (*(cp = element + strlen (element) - 1) == '*') \ *cp = NULL, ak -> ak_flags |= right; \ if ((element = strdup (element)) == NULL) \ adios (NULLCP, "out of memory"); do_field (vec[0], ak -> ak_host, AK_HWL, AK_HWR); do_field (vec[1], ak -> ak_user, AK_UWL, AK_UWR); #undef do_field if (vecp == 2) ak -> ak_template = "", ak -> ak_flags |= AK_INV; else if ((ak -> ak_template = strdup (vec[2])) == NULL) adios (NULLCP, "out of memory"); insque (ak, AHead -> ak_back); } (void) fclose (fp); } if ((ak = (struct aka *) calloc (1, sizeof *ak)) == NULL) adios (NULLCP, "out of memory"); ak -> ak_host = ak -> ak_user = ""; ak -> ak_flags = AK_WILD; if ((cp = alias2name (prefix)) == NULL) cp = prefix; (void) sprintf (buffer, "%s@CN=$u", cp); if ((ak -> ak_template = strdup (buffer)) == NULL) adios (NULLCP, "out of memory"); insque (ak, AHead -> ak_back); } /* \f ARGINIT */ static arginit (vecp, vec) int vecp; char **vec; { int n; register char *ap, *cp; if (myname = rindex (*vec, '/')) myname++; if (myname == NULL || *myname == NULL) myname = *vec; isodetailor (myname, 1); if ((ap = getenv ("FACEPROC")) && (cp = index (ap, ' ')) && sscanf (++cp, "%d", &n) == 1 && n >= 1) portsw = n; for (vecp--, vec++; ap = *vec; vecp--, vec++) if (*ap == '-') switch (*++ap) { case 'd': debug++; break; case 'e': errsw++; break; case 'h': if ((ap = *++vec) == NULL || *ap == '-') adios (NULLCP, "usage: %s -h prefix", myname); prefix = ap; break; case 'p': if ((ap = *++vec) == NULL || sscanf (ap, "%d", &portsw) != 1 || portsw < 1) adios (NULLCP, "usage: %s -p port", myname); vecp--; break; case 'r': recording++; break; case 's': if ((ap = *++vec) == NULL || sscanf (ap, "%d", &sleepsw) != 1 || sleepsw < 1) adios (NULLCP, "usage: %s -s seconds", myname); vecp--; break; case 'u': ppidsw = getppid (); break; default: adios (NULLCP, "unknown switch -%s", ap); } else if (*ap == '=') geometry = ap; else if ((cp = rindex (ap, ':')) && sscanf (++cp, "%d", &n) == 1) display = ap; else adios (NULLCP, "usage: %s [switches] host:display", myname); if (debug) ll_dbinit (pgm_log, myname); else ll_hdinit (pgm_log, myname); init_aka (); if ((DISP = XOpenDisplay (display)) == NULL) adios (NULLCP, "unable to open display \"%s\"", XDisplayName (display)); SCRN = DefaultScreen (DISP); } /* \f */ static envinit () { int i, pid; if (debug) return; for (i = 0; (pid = fork ()) == NOTOK && i < 5; i++) sleep (5); switch (pid) { case NOTOK: case OK: break; default: exit (0); } } /* \f */ static display_X () { if (mywindow == NULL) { int bwidth; char *opt, def[BUFSIZ]; XSizeHints hints; XSetWindowAttributes xswattrs; unsigned long xswattrs_mask; forepix = XCreateGC (DISP, RootWindow (DISP, SCRN), 0L, (XGCValues *) NULL); highpix = XCreateGC (DISP, RootWindow (DISP, SCRN), 0L, (XGCValues *) NULL); XCopyGC (DISP, DefaultGC (DISP, SCRN), (1L<<(GCLastBit+1)) - 1, forepix); XCopyGC (DISP, DefaultGC (DISP, SCRN), (1L<<(GCLastBit+1)) - 1, highpix); if ((opt = XGetDefault (DISP, myname, "ReverseVideo")) && strcmp (opt, "on") == 0) { XSetForeground(DISP, forepix, WhitePixel(DISP, SCRN)); XSetForeground(DISP, highpix, WhitePixel(DISP, SCRN)); backpix = BlackPixel(DISP, SCRN); bdrpix = WhitePixel(DISP, SCRN); XSetFunction(DISP, forepix, GXand); XSetFunction(DISP, highpix, GXand); } else { XSetForeground(DISP, forepix, BlackPixel(DISP, SCRN)); XSetForeground(DISP, highpix, BlackPixel(DISP, SCRN)); backpix = WhitePixel(DISP, SCRN); bdrpix = BlackPixel(DISP, SCRN); XSetFunction(DISP, forepix, GXor); XSetFunction(DISP, highpix, GXor); } XSetBackground (DISP, forepix, backpix); XSetBackground (DISP, highpix, backpix); if (opt = XGetDefault (DISP, myname, "BorderWidth")) bwidth = atoi (opt); else bwidth = 2; myframe.bdrwidth = bwidth; myframe.height = myim -> height; if (myframe.height + bwidth * 2 > DisplayHeight (DISP, SCRN)) myframe.height = DisplayHeight (DISP, SCRN) - bwidth * 2; myframe.width = myim -> width; if (myframe.width + bwidth * 2 > DisplayWidth (DISP, SCRN)) myframe.width = DisplayWidth (DISP, SCRN) - bwidth * 2; myframe.x = DisplayWidth (DISP, SCRN) - (myframe.width + bwidth * 2); myframe.y = 0; (void) sprintf (def, "=%dx%d+%d+%d", myframe.width, myframe.height, myframe.x, myframe.y); if (debug) fprintf (stderr, "def: %s, myframe: =%dx%d+%d+%d/%d\n", def, myframe.width, myframe.height, myframe.x, myframe.y, myframe.bdrwidth); hints.width = myim -> width; hints.height = myim -> height; hints.x = hints.y = 0; hints.flags = PSize | PPosition; xswattrs.border_pixel = bdrpix; xswattrs.background_pixel = backpix; xswattrs_mask = CWBackPixel | CWBorderPixel; mywindow = XCreateWindow (DISP, RootWindow (DISP, SCRN), myframe.x, myframe.y, myframe.width, myframe.height, myframe.bdrwidth, 0, InputOutput, (Visual *) CopyFromParent, xswattrs_mask, &xswattrs); XSetStandardProperties (DISP, mywindow, myname, "Face Agent", None, (char **) 0, 0, &hints); XSelectInput (DISP, mywindow, ExposureMask | StructureNotifyMask); XMapWindow (DISP, mywindow); mapped = parent = 0; } else Redisplay (); eventfd = ConnectionNumber (DISP); eventfx = XWINser; alarmfx = ALRMser; XWINser (0); } /* \f */ static Redisplay () { int sx, sy, dx, dy; unsigned int h, w; XImage *image; Pixmap pixmap; if (myim == NULL) { XClearWindow (DISP, mywindow); return; } sx = max (myim -> width - (int) myframe.width, 0) / 2; sy = max (myim -> height - (int) myframe.height, 0) / 2; dx = max ((int) myframe.width - myim -> width, 0) / 2; dy = max ((int) myframe.height - myim -> height, 0) / 2; w = min (myframe.width, myim -> width); h = min (myframe.height, myim -> height); if (debug) { fprintf (stderr, "im: %dx%d frame:%dx%d\n", myim -> width, myim -> height, myframe.width, myframe.height); fprintf (stderr, "sx=%d sy=%d dx=%d dy=%d w=%d h=%d\n", sx, sy, dx, dy, w, h); } pixmap = XCreateBitmapFromData (DISP, mywindow, myim -> data -> qb_forw -> qb_data, (unsigned int) myim -> width, (unsigned int) myim -> height); if (pixmap == NULL) adios (NULLCP, "XCreateBitmapFromData failed"); image = XGetImage (DISP, pixmap, 0, 0, (unsigned int) myim -> width, (unsigned int) myim -> height, XAllPlanes (), XYPixmap); image -> bitmap_unit = image -> bitmap_pad = 8; image -> byte_order = image -> bitmap_bit_order = MSBFirst; XClearWindow (DISP, mywindow); XPutImage (DISP, mywindow, forepix, image, sx, sy, dx, dy, w, h); XDestroyImage (image); } /* \f */ static int ALRMser () { if (mywindow && mapped) { if (parent) XClearWindow (DISP, mywindow); else XUnmapWindow (DISP, mywindow); } if (myim) free_IMAGE_Image (myim), myim = NULL; } /* \f */ /* ARGSUSED */ static int XWINser (io) int io; { int ww, wh; XEvent xevent; register XEvent *xe = &xevent; while (XPending (DISP)) { XNextEvent (DISP, xe); switch (xe -> type) { case Expose: if (debug) fprintf (stderr, "Expose %d\n", ((XExposeEvent *) xe) -> count); if (myim) { if (((XExposeEvent *) xe) -> count > 0) break; mapped = 1; Redisplay (); } else { unmap: ; if (parent) XClearWindow (DISP, mywindow); else XUnmapWindow (DISP, mywindow); } break; case MapNotify: if (debug) fprintf (stderr, "MapNotify (0x%x)\n", myim); if (myim) { mapped = 1; Redisplay (); } else goto unmap; break; case ConfigureNotify: if (debug) fprintf (stderr, "ConfigureNotify %dx%d\n", ((XConfigureEvent *) xe) -> height, ((XConfigureEvent *) xe) -> width); if ((wh = ((XConfigureEvent *) xe) -> height) > 0 && (ww = ((XConfigureEvent *) xe) -> width) > 0) myframe.height = wh, myframe.width = ww; break; case UnmapNotify: if (debug) fprintf (stderr, "UnmapNotify\n"); mapped = 0; break; case ReparentNotify: if (debug) fprintf (stderr, "ReparentNotify\n"); parent = 1; break; default: if (debug) fprintf (stderr, "Event %d\n", xe -> type); break; } } } /* \f SOCKET */ int startsocket (portno) int portno; { struct sockaddr_in in_socket; register struct sockaddr_in *isock = &in_socket; isock -> sin_family = AF_INET; isock -> sin_port = htons ((u_short) portno); isock -> sin_addr.s_addr = INADDR_ANY; if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK) adios ("socket", "unable to create"); if (bind (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK) adios ("socket", "unable to bind"); } /* \f */ int readsocket (buffer) char *buffer; { int cc; for (;;) { int i, nfds; fd_set imask; struct sockaddr_in in_socket; struct sockaddr_in *isock = &in_socket; FD_ZERO (&imask); nfds = sd + 1; FD_SET (sd, &imask); if (eventfd != NOTOK) { (*eventfx) (0); if (eventfd >= nfds) nfds = eventfd + 1; FD_SET (eventfd, &imask); } if (xselect (nfds, &imask, NULLFD, NULLFD, sleepsw) <= 0) { if (errno == EINTR) continue; if (ppidsw > 0 && kill (ppidsw, 0) == NOTOK) { (void) close (sd); return NOTOK; } if (alarmfx) (*alarmfx) (); continue; } if (ppidsw > 0 && kill (ppidsw, 0) == NOTOK) { (void) close (sd); return NOTOK; } if (eventfd != NOTOK && FD_ISSET (eventfd, &imask)) (*eventfx) (1); if (!FD_ISSET (sd, &imask)) continue; i = sizeof *isock; if ((cc = recvfrom (sd, buffer, BUFSIZ, 0, (struct sockaddr *) isock, &i)) == NOTOK) { if (errno == EINTR) continue; adios ("failed", "recvfrom socket"); } break; } buffer[cc] = NULL; return OK; }