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