DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T x

⟦dd3aa4991⟧ TextFile

    Length: 18393 (0x47d9)
    Types: TextFile
    Names: »xface.c«

Derivation

└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape
    └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« 
        └─⟦d3ac74d73⟧ 
            └─⟦this⟧ »isode-5.0/others/image/xface.c« 

TextFile

/* 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;
}