DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

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

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T m

⟦827a178f2⟧ TextFile

    Length: 24395 (0x5f4b)
    Types: TextFile
    Names: »misc.c«

Derivation

└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS 
    └─ ⟦91c658230⟧ »DATA« 
        └─⟦5d656759a⟧ 
            └─⟦7d9cab9a9⟧ 
└─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3
    └─ ⟦fc9b38f02⟧ »DATA« 
        └─⟦8e9e227a9⟧ 
            └─⟦7d9cab9a9⟧ 
                └─ ⟦this⟧ »./misc.c« 
└─⟦5f3412b64⟧ Bits:30000745 8mm tape, Rational 1000, ENVIRONMENT 12_6_5 TOOLS 
    └─ ⟦91c658230⟧ »DATA« 
        └─⟦5d656759a⟧ 
            └─⟦85ff0a957⟧ 
└─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3
    └─ ⟦fc9b38f02⟧ »DATA« 
        └─⟦8e9e227a9⟧ 
            └─⟦85ff0a957⟧ 
                └─ ⟦this⟧ »./misc.c« 
└─⟦d10a02448⟧ Bits:30000409 8mm tape, Rational 1000, ENVIRONMENT, D_12_7_3
    └─ ⟦fc9b38f02⟧ »DATA« 
        └─⟦8e9e227a9⟧ 
            └─⟦e9895db93⟧ 
                └─ ⟦this⟧ »./misc.c« 

TextFile

/*
 *	$XConsortium: misc.c,v 1.29 89/01/04 12:25:17 jim Exp $
 */


#include <X11/copyright.h>

/*
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 *
 *                         All Rights Reserved
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of Digital Equipment
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission.
 *
 *
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/file.h>
#ifdef ultrix
#include <malloc.h>
#include <fcntl.h>
#else
#include <sys/fcntl.h>
#endif
#include <ctype.h>
#include <pwd.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include "ptyx.h"
#include "data.h"
#include "error.h"
#include <X11/cursorfont.h>
#include "gray.ic"
#include "wait.ic"
#include "waitmask.ic"
#define XK_MISCELLANY
#define XK_LATIN1
#include <X11/keysymdef.h>
#include <X11/Shell.h>
#include <X11/Xmu.h>
#include "ratmenu.h"

#ifndef ultrix
extern char *malloc();
#endif
extern char *mktemp();
extern void exit();
extern void perror();
extern void abort();

#ifndef lint
static char rcs_id[] = "$XConsortium: misc.c,v 1.29 89/01/04 12:25:17 jim Exp $";
#endif	/* lint */

#define GEBDEBUG       0

xevents()
{
	XEvent event;
	register TScreen *screen = &term->screen;

	if(screen->scroll_amt)
		FlushScroll(screen);
	XPending (screen->display);
	do {
		if (waitingForTrackInfo)
			return;
#if GEBDEBUG
		fprintf(stderr,"Do an XtNextEvent [%ld]\n",
			(long)QLength(screen->display));
#endif
		XNextEvent (screen->display, &event);
#if GEBDEBUG
		/* PrintEventType is from ../../lib/Xt/TMstate.c.  I've made
		 * it external so we can have debug printout. */
		{   Widget w = XtWindowToWidget(event.xany.display,
						event.xany.window);
		    char   eventname[64];
		    extern String PrintEventType();
		    (void)PrintEventType(eventname,event.xany.type);
		    fprintf(stderr,"Event %s window=%lx widget=%s.%s\n",
			    eventname,
			    (unsigned long)event.xany.window,
			    (w ? w->core.name : NULL),
			    (w ? w->core.widget_class->core_class.class_name
			       : NULL) );
		}
#endif
		XtDispatchEvent(&event);
#if GEBDEBUG
		fprintf(stderr,"QLength after XtDispatch = %ld\n",
			(long)QLength(screen->display));
#endif
	} while (QLength(screen->display) > 0);
}


Cursor make_colored_cursor (cursorindex, fg, bg)
	int cursorindex;			/* index into font */
	unsigned long fg, bg;			/* pixel value */
{
	register TScreen *screen = &term->screen;
	Cursor c;
	register Display *dpy = screen->display;
	
	c = XCreateFontCursor (dpy, cursorindex);
	if (c == (Cursor) 0) return (c);

	recolor_cursor (c, fg, bg);
	return (c);
}

/* ARGSUSED */
void HandleKeyPressed(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    register TScreen *screen = &term->screen;

#ifdef ACTIVEWINDOWINPUTONLY
    if (w == ((Widget)term))
#endif
	Input (&term->keyboard, screen, (XKeyPressedEvent*)event, False);
}

/* ARGSUSED */
void HandleEightBitKeyPressed(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    register TScreen *screen = &term->screen;

#ifdef ACTIVEWINDOWINPUTONLY
    if (w == (screen->TekEmu ? (Widget)tekWidget : (Widget)term))
#endif
	Input (&term->keyboard, screen, event, True);
}

/* ARGSUSED */
void HandleStringEvent(w, event, params, nparams)
    Widget w;
    XEvent *event;
    String *params;
    Cardinal *nparams;
{
    register TScreen *screen = &term->screen;

#ifdef ACTIVEWINDOWINPUTONLY
    if (w != ((Widget)term)) return;
#endif

    if (*nparams != 1) return;

    if ((*params)[0] == '0' && (*params)[1] == 'x' && (*params)[2] != '\0') {
	char c, *p, hexval[2];
	hexval[0] = hexval[1] = 0;
	for (p = *params+2; (c = *p); p++) {
	    hexval[0] *= 16;
	    if (isupper(c)) c = tolower(c);
	    if (c >= '0' && c <= '9')
		hexval[0] += c - '0';
	    else if (c >= 'a' && c <= 'f')
		hexval[0] += c - 'a' + 10;
	    else break;
	}
	if (c == '\0')
	    StringInput (screen, hexval);
    }
    else {
	StringInput (screen, *params);
    }
}

XtIntervalId ForceFrontTimer = (XtIntervalId)0;
Window	     real_parent     = None;

void ForceToFront( addr, timer )
     caddr_t		addr;
     XtIntervalId	timer;
/******************************************************************************
* Called when our ForceFrontTimer expires.  We try to bring our window to the
* "front" of the window display stack so that it is fully visible.
******************************************************************************/
{
    XWindowChanges conf;
    Widget	   w = (Widget)term;

/*--See if we have determined our "real" parent yet.  Our normal parent is
 *  XtParent(w) but we may have had our parent reparented by the window
 *  manager.  So, see if our XtParent(w) has a parent that we don't know
 *  about. */

    if (real_parent == None) {
	Window	 root;
	Window	*children;
	unsigned int nchildren;
	if (XQueryTree( XtDisplay(w), XtWindow(XtParent(w)),
		        &root, &real_parent,
		        &children, &nchildren )) {
	    if (children) { XFree( (char*)children ); }
	    if (root == real_parent) { real_parent = XtWindow(XtParent(w)); }
	} else {
	    real_parent = None;
	}
    }

/*--Ask that our top-level window (the real one) be placed on the top of the
 *  display stack. */

    conf.stack_mode = Above;
    XConfigureWindow( XtDisplay(term),
		      ((real_parent != None)
		       ? real_parent
		       : XtWindow(XtParent(w))),
		      CWStackMode,
		      &conf );
    ForceFrontTimer = (XtIntervalId)0;

} /* ForceToFront */


/*ARGSUSED*/
void HandleEnterWindow(w, eventdata, event)
Widget w;
register XEnterWindowEvent *event;
caddr_t eventdata;
{
    extern Boolean    AutoRaise;
    extern int        AutoRaiseDelay;
    register TScreen *screen = &term->screen;

#ifdef ACTIVEWINDOWINPUTONLY
    if (w == XtParent((Widget)term)) 
#endif
      if (((event->detail) != NotifyInferior) &&
	  event->focus &&
	  !(screen->select & FOCUS)) {
	  selectwindow(screen, INWINDOW);
	  if (AutoRaise) {
	      ForceFrontTimer =
		XtAddTimeOut( (unsigned long)AutoRaiseDelay,
			      ForceToFront,
			      (caddr_t)NULL );
	  }
      }
}

/*ARGSUSED*/
void HandleLeaveWindow(w, eventdata, event)
Widget w;
register XEnterWindowEvent *event;
caddr_t eventdata;
{
    register TScreen *screen = &term->screen;

#ifdef ACTIVEWINDOWINPUTONLY
    if (w == XtParent((Widget)term)) 
#endif
      if (((event->detail) != NotifyInferior) &&
	  event->focus &&
	  !(screen->select & FOCUS)) {
	  unselectwindow(screen, INWINDOW);
	  if (ForceFrontTimer != (XtIntervalId)0) {
	      XtRemoveTimeOut( ForceFrontTimer );
	      ForceFrontTimer = (XtIntervalId)0;
	  }
      }

}


Bool Button1Click( dpy, event, Click )
     Display		*dpy;
     register XEvent	*event;
     char		*Click;
/******************************************************************************
* Return TRUE if event is a Button 1 Press.
******************************************************************************/
{

    if (*Click) {
	if (event->xany.type == ButtonRelease &&
	    event->xbutton.button == Button1) { return TRUE; }
    } else {
	if (event->xany.type == ButtonPress &&
	    event->xbutton.button == Button1) { return TRUE; }
    }
    return FALSE;

} /* Button1Click */


/*ARGSUSED*/
void HandleFocusChange(w, eventdata, event)
Widget w;
register XFocusChangeEvent *event;
caddr_t eventdata;
{
        register TScreen *screen = &term->screen;

/*--Make sure that the cursor is whereever it needs to be in whatever state. */

    if(screen->cursor_set &&
       (screen->cursor_col != screen->cur_col ||
	screen->cursor_row != screen->cur_row)) {
	if(screen->cursor_state)
	  HideCursor();
	ShowCursor();
    } else if(screen->cursor_set != screen->cursor_state) {
	if(screen->cursor_set)
	  ShowCursor();
	else
	  HideCursor();
    }

/*--If we just got the focus then set up our window and cursor. */

    if(event->type == FocusIn) {
	selectwindow(screen,
		     (event->detail == NotifyPointer) ? INWINDOW :
		     					FOCUS);

/*--If we get one of these then we are probably working with a click-to-type
 *  window manager.  In this case then we also usually get a button1 click
 *  when we get the focus; it is the most likely way we will get it; sigh.
 *  Eat that first button1 click. */

	{   XEvent	event;
	    char	Click = 0;
	    if (XCheckIfEvent( XtDisplay(term), &event,
			      Button1Click, &Click )) {
		Click = 1;
		(void)XCheckIfEvent( XtDisplay(term), &event,
				    Button1Click, &Click );
	    }
	}

/*--We just lost the focus. */

    } else {
	unselectwindow(screen,
		       (event->detail == NotifyPointer) ? INWINDOW :
		       					  FOCUS);
	if (screen->grabbedKbd && (event->mode == NotifyUngrab)) {
	    screen->grabbedKbd = FALSE;
	    ReverseVideo(term);
	    XBell(screen->display, 100);
	}
    }
}


char	KeyCodeTable_Xlate[128][5];	/* Xlation for SelectionReceived */
Boolean	KeyCodeTable_ShiftLock;		/* Lock == ShiftLock (!= CapsLock) */
Boolean KeyCodeTable_Inited = FALSE;	/* Are tables good? */
KeySym	KeyCodeTable_Shifted[256];	/* Shifted KeySym for a given key */
KeySym	KeyCodeTable_Unshifted[256];	/* Unshifted KeySym for given key */


/*ARGSUSED*/
void HandleMappingNotify( event )
register XMappingEvent *event;
{
	Display		*dpy = term->screen.display;
	KeySym  	*keyboard;
	XModifierKeymap	*modifier;
	int		 per_keycode;

    {
	register KeySym		*kmap;
	register char		*cp;
	         char		*orig;
	register unsigned	 i;
	register int		 j;
	register KeySym		 ks;

/*--Get the latest Keyboard Mapping */

	kmap = XGetKeyboardMapping( 
			dpy,
			dpy->min_keycode,
			(int)(dpy->max_keycode - dpy->min_keycode + 1),
			&per_keycode );
	keyboard = kmap;

/*--Zap our KeyCode->KeySym translation table. */

	KeyCodeTable_ShiftLock = FALSE;
	for (i = 256; i > 0; ) {
		KeyCodeTable_Shifted[--i] = NoSymbol;
		KeyCodeTable_Unshifted[i] = NoSymbol;
	}

/*--Set up our SelectionReceived (paste) translation buffer; characters stuffed
 *  down the PTY as a result of a Paste operation will be translated according
 *  to this table.  This is the best we can do for now; something that looks
 *  like the Ascii code for 'A' might have been caused by pressing an Umlaut
 *  button or something but we have no way of knowing that at this point; we
 *  only know we have the Ascii code for 'A'. */

	j = 0;
	/*--Set up all of the control characters; octal 000..037. */
	for (i = XK_at; i <= XK_underscore; j++,i++) {
	    orig = &KeyCodeTable_Xlate[j][0];
	    cp = &orig[1];
	    DoRMaskChar( cp, RControlMask, i );
	    orig[0] = (char)(cp-orig-1);
	}
	/*--Set up all of the printing characters; octal 040..0176. */
	for (i = XK_space; i <= XK_asciitilde; j++,i++) {
	    orig = &KeyCodeTable_Xlate[j][0];
	    cp = &orig[1];
	    DoRChar( cp, i );
	    orig[0] = (char)(cp-orig-1);
	}
	/*--Set up the rubout character; octal 177. */
	orig = &KeyCodeTable_Xlate[j][0];
	cp = &orig[1];
	DoRChar( cp, XK_Delete );
	orig[0] = (char)(cp-orig-1);

/*--Special case; use MENU_RETURN pseudo-key for pasting newlines.  We want
 *  to use the R1000 Editor.Line.Insert command rather than Editor.Line.Indent.
 */

	orig = &KeyCodeTable_Xlate['\n'][0];
	cp = &orig[1];
	DoRChar( cp, MENU_RETURN );
	orig[0] = (char)(cp-orig-1);

/*--Run through the map and record what we find. */

	for (i = dpy->min_keycode, j = 0;
	     i <= dpy->max_keycode;
	     i++, j+=per_keycode) {
	    ks = kmap[j];
	    KeyCodeTable_Unshifted[i] = ks;
	    if ((per_keycode == 1 || kmap[j+1] == NoSymbol) &&
		ks >= XK_A &&
		ks <= XK_Z) {
		KeyCodeTable_Shifted[i]   = ks;
		KeyCodeTable_Unshifted[i] = ks + (XK_a - XK_A);
	    } else {
		KeyCodeTable_Shifted[i]   = kmap[j+1];
	    }
	    if (ks == XK_Tab) {
		/*--If we happen to find a "Tab" key then use that keycode
		 *  for pasted ^I characters. */
		orig = &KeyCodeTable_Xlate['\t'][0];
		cp = &orig[1];
		DoRChar( cp, ks );
		orig[0] = (char)(cp-orig-1);
	    }
	}
    }
    {
	register XModifierKeymap *mm;
		 KeyCode	 *kcp;
	register KeyCode	  kc;
	register int		  i;
	register int		  j;

/*--Get the latest Modifier Mapping. */

	mm = XGetModifierMapping( dpy );
	modifier = mm;

/*--Run through it and zap the modifiers in the KeyCodeTables. */

#if TRUE		/* For now we treat Mod2..Mod5 as normal keys. */
	for (i = ShiftMapIndex; i <= Mod1MapIndex; i++) {
#else
	for (i = ShiftMapIndex; i <= Mod5MapIndex; i++) {
#endif
		kcp = &mm->modifiermap[i*mm->max_keypermod];
		for (j = mm->max_keypermod; j > 0; j--) {
			if ((kc = *kcp++) == 0) { break; }
			KeyCodeTable_Shifted[kc] = NoSymbol;
			KeyCodeTable_Unshifted[kc] = NoSymbol;
		}
	} 

/*--Now decide the fate of the Lock key(s). */

	KeyCodeTable_ShiftLock = FALSE;
	kcp = &mm->modifiermap[LockMapIndex*mm->max_keypermod];
	for (j = mm->max_keypermod; j > 0; j--) {
		if ((kc = *kcp++) == 0) { break; }
		if (keyboard[(kc - dpy->min_keycode) * per_keycode]
			== XK_Shift_Lock) {
			KeyCodeTable_ShiftLock = TRUE;
			break;
		}
	}
    }

/*--We are inited at this point no matter what happened above. */

	XFree( (char*)keyboard );
	XFreeModifiermap( modifier );
	KeyCodeTable_Inited = TRUE;

}



selectwindow(screen, flag)
register TScreen *screen;
register int flag;
{
    if(screen->cursor_state &&
       (screen->cursor_col != screen->cur_col ||
	screen->cursor_row != screen->cur_row))
      HideCursor();
    screen->select |= flag;
    if(screen->cursor_state)
      ShowCursor();
}

unselectwindow(screen, flag)
register TScreen *screen;
register int flag;
{
    register int i;

    if (screen->always_highlight) return;

    screen->select &= ~flag;
    if(screen->cursor_state &&
       (screen->cursor_col != screen->cur_col ||
	screen->cursor_row != screen->cur_row))
      HideCursor();
    if(screen->cursor_state)
      ShowCursor();
}

Pixmap Make_tile(width, height, bits, foreground, background, depth)
	unsigned int width, height, depth;
	Pixel foreground, background;
	char *bits;
{
	register GC gc;
	register Pixmap pix;
	register TScreen *screen = &term->screen;
	XGCValues gcVals;
	XImage tileimage;

        pix = (Pixmap)XCreatePixmap(screen->display, 
	  DefaultRootWindow(screen->display), width, height, depth);
	gcVals.foreground = foreground;
	gcVals.background = background;
	gc = XCreateGC(screen->display, (Drawable) pix, 
	  GCForeground+GCBackground, &gcVals);
	tileimage.height = height;
	tileimage.width = width;
	tileimage.xoffset = 0;
	tileimage.format = XYBitmap;
	tileimage.data = bits;
	tileimage.byte_order = LSBFirst;
	tileimage.bitmap_unit = 8;
	tileimage.bitmap_bit_order = LSBFirst;
	tileimage.bitmap_pad = 8;
	tileimage.bytes_per_line = (width+7)>>3;
	tileimage.depth = 1;
        XPutImage(screen->display, pix, gc, &tileimage, 0, 0, 0, 0, width, height);
        XFreeGC (screen->display, gc);
	return(pix);
}


Pixmap make_gray(fg, bg, depth)
Pixel fg, bg;
{
	return(Make_tile(gray_width, gray_height, gray_bits, fg, bg, depth));
}

Bell()
{
    extern XtermWidget term;
    register TScreen *screen = &term->screen;
    register Pixel xorPixel = screen->foreground ^ term->core.background_pixel;
    XGCValues gcval;
    GC visualGC;

    if(screen->visualbell) {
	gcval.function = GXxor;
	gcval.foreground = xorPixel;
	visualGC = XtGetGC((Widget)term, GCFunction+GCForeground, &gcval);
	XFillRectangle(
		       screen->display,
		       VWindow(screen), 
		       visualGC,
		       0, 0,
		       (unsigned) FullWidth(screen),
		       (unsigned) FullHeight(screen));
	XFlush(screen->display);
	XFillRectangle(
		       screen->display,
		       VWindow(screen), 
		       visualGC,
		       0, 0,
		       (unsigned) FullWidth(screen),
		       (unsigned) FullHeight(screen));
    } else
      XBell(screen->display, 0);
}

Redraw()
{
	extern XtermWidget term;
	register TScreen *screen = &term->screen;
	XExposeEvent event;

	event.type = Expose;
	event.display = screen->display;
	event.x = 0;
	event.y = 0;
	event.count = 0; 
	
	if(VWindow(screen)) {
	        event.window = VWindow(screen);
		event.width = term->core.width;
		event.height = term->core.height;
		(*term->core.widget_class->core_class.expose)(term, &event, NULL);
		if(screen->scrollbar) 
			(*screen->scrollWidget->core.widget_class->core_class.expose)(screen->scrollWidget, &event, NULL);
		}

}

StartLog(screen)
register TScreen *screen;
{
	register char *cp;
	register int i;
	static char *log_default;
	char *rindex();
	extern void logpipe();
#ifdef SYSV
	/* SYSV has another pointer which should be part of the
	** FILE structure but is actually a separate array.
	*/
	unsigned char *old_bufend;
#endif	/* SYSV */

	if(screen->logging || (screen->inhibit & I_LOG))
		return;
	if(screen->logfile == NULL || *screen->logfile == 0) {
		if(screen->logfile)
			free(screen->logfile);
		if(log_default == NULL)
			mktemp(log_default = log_def_name);
		if((screen->logfile = (char*)malloc((unsigned)strlen(log_default) + 1)) == NULL)
			return;
		strcpy(screen->logfile, log_default);
	}
	if(*screen->logfile == '|') {	/* exec command */
		int p[2];
		static char *shell;

		if(pipe(p) < 0 || (i = fork()) < 0)
			return;
		if(i == 0) {	/* child */
			close(p[1]);
			dup2(p[0], 0);
			close(p[0]);
			dup2(fileno(stderr), 1);
			dup2(fileno(stderr), 2);
#ifdef SYSV
			old_bufend = _bufend(stderr);
#endif	/* SYSV */
#ifdef ultrix
			if (fileno(stderr) != 1 && fileno(stderr) != 2)
			  dup2( 2, fileno(stderr) );
#else
			close(fileno(stderr));
			fileno(stderr) = 2;
#endif
#ifdef SYSV
			_bufend(stderr) = old_bufend;
#endif	/* SYSV */
			close(screen->display->fd);
			close(screen->respond);
			if(!shell) {
				register struct passwd *pw;
				char *getenv();
				struct passwd *getpwuid();

				if(((cp = getenv("SHELL")) == NULL || *cp == 0)
				 && ((pw = getpwuid(screen->uid)) == NULL ||
				 *(cp = pw->pw_shell) == 0) ||
				 (shell = (char*)malloc((unsigned) strlen(cp) + 1)) == NULL)
					shell = "/bin/sh";
				else
					strcpy(shell, cp);
			}
			signal(SIGHUP, SIG_DFL);
			signal(SIGCHLD, SIG_DFL);
			setgid(screen->gid);
			setuid(screen->uid);
			execl(shell, shell, "-c", &screen->logfile[1], 0);
			fprintf(stderr, "%s: Can't exec `%s'\n", xterm_name,
			 &screen->logfile[1]);
			exit(ERROR_LOGEXEC);
		}
		close(p[0]);
		screen->logfd = p[1];
		signal(SIGPIPE, logpipe);
	} else {
		if(access(screen->logfile, F_OK) == 0) {
			if(access(screen->logfile, W_OK) < 0)
				return;
		} else if(cp = rindex(screen->logfile, '/')) {
			*cp = 0;
			i = access(screen->logfile, W_OK);
			*cp = '/';
			if(i < 0)
				return;
		} else if(access(".", W_OK) < 0)
			return;
		if((screen->logfd = open(screen->logfile, O_WRONLY | O_APPEND |
		 O_CREAT, 0644)) < 0)
			return;
		chown(screen->logfile, screen->uid, screen->gid);

	}
	screen->logstart = bptr;
	screen->logging = TRUE;
}

CloseLog(screen)
register TScreen *screen;
{
	if(!screen->logging || (screen->inhibit & I_LOG))
		return;
	FlushLog(screen);
	close(screen->logfd);
	screen->logging = FALSE;
}

FlushLog(screen)
register TScreen *screen;
{
	register Char *cp;
	register int i;

	cp = bptr;
	if((i = cp - screen->logstart) > 0)
		write(screen->logfd, screen->logstart, i);
	screen->logstart = buffer;
}

void logpipe()
{
	register TScreen *screen = &term->screen;

#ifdef SYSV
	(void) signal(SIGPIPE, SIG_IGN);
#endif	/* SYSV */
	if(screen->logging)
		CloseLog(screen);
}

do_osc(func)
int (*func)();
{
	register TScreen *screen = &term->screen;
	register int mode, c;
	register char *cp;
	char buf[512];
	Bool okay = True;

	/* 
	 * lines should be of the form <ESC> ] number ; string <BEL>
	 *
	 * where number is one of 0, 1, 2, or 46
	 */
	mode = 0;
	while(isdigit(c = (*func)()))
		mode = 10 * mode + (c - '0');
	if (c != ';') okay = False;
	cp = buf;
	while(isprint((c = (*func)()) & 0x7f))
		*cp++ = c;
	if (c != 7) okay = False;
	*cp = 0;
	if (okay) switch(mode) {
	 case 0:	/* new icon name and title*/
		Changename(buf);
		Changetitle(buf);
		break;

	 case 1:	/* new icon name only */
		Changename(buf);
		break;

	 case 2:	/* new title only */
		Changetitle(buf);
		break;

	 case 46:	/* new log file */
		if((cp = (char*)malloc((unsigned)strlen(buf) + 1)) == NULL)
			break;
		strcpy(cp, buf);
		if(screen->logfile)
			free(screen->logfile);
		screen->logfile = cp;
		break;
	}
}

static ChangeGroup(attribute, value)
     String attribute;
     XtArgVal value;
{
	extern Widget toplevel;
	Arg args[1];

	XtSetArg( args[0], attribute, value );
	XtSetValues( toplevel, args, 1 );
}

Changename(name)
register char *name;
{
    ChangeGroup( XtNiconName, (XtArgVal)name );
}

Changetitle(name)
register char *name;
{
    ChangeGroup( XtNtitle, (XtArgVal)name );
}

#ifndef DEBUG
/* ARGSUSED */
#endif
Panic(s, a)
char	*s;
int a;
{
#ifdef DEBUG
	if(debug) {
		fprintf(stderr, "%s: PANIC!	", xterm_name);
		fprintf(stderr, s, a);
		fputs("\r\n", stderr);
		fflush(stderr);
	}
#endif	/* DEBUG */
}

char *SysErrorMsg (n)
    int n;
{
    extern char *sys_errlist[];
    extern int sys_nerr;

    return ((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error");
}


SysError (i)
int i;
{
	int oerrno;

	oerrno = errno;
	/* perror(3) write(2)s to file descriptor 2 */
	fprintf (stderr, "%s: Error %d, errno %d: ", xterm_name, i, oerrno);
	fprintf (stderr, "%s\n", SysErrorMsg (oerrno));
	Cleanup(i);
}

Error (i)
int i;
{
	fprintf (stderr, "%s: Error %d\n", xterm_name, i);
	Cleanup(i);
}


/*
 * cleanup by sending SIGHUP to client processes
 */
Cleanup (code)
int code;
{
	extern XtermWidget term;
	register TScreen *screen;

	screen = &term->screen;
	if (screen->pid > 1) {
	    (void) killpg (screen->pid, SIGHUP);
	}
	Exit (code);
}

/*
 * sets the value of var to be arg in the Unix 4.2 BSD environment env.
 * Var should end with '=' (bindings are of the form "var=value").
 * This procedure assumes the memory for the first level of environ
 * was allocated using calloc, with enough extra room at the end so not
 * to have to do a realloc().
 */
Setenv (var, value)
register char *var, *value;
{
	extern char **environ;
	register int index = 0;
	register int len = strlen(var);

	while (environ [index] != NULL) {
	    if (strncmp (environ [index], var, len) == 0) {
		/* found it */
		environ[index] = (char *)malloc ((unsigned)len + strlen (value) + 1);
		strcpy (environ [index], var);
		strcat (environ [index], value);
		return;
	    }
	    index ++;
	}

#ifdef DEBUG
	if (debug) fputs ("expanding env\n", stderr);
#endif	/* DEBUG */

	environ [index] = (char *) malloc ((unsigned)len + strlen (value) + 1);
	(void) strcpy (environ [index], var);
	strcat (environ [index], value);
	environ [++index] = NULL;
}

/*
 * returns a pointer to the first occurrence of s2 in s1,
 * or NULL if there are none.
 */
char *strindex (s1, s2)
register char	*s1, *s2;
{
	register char	*s3;
	char		*index();
	int s2len = strlen (s2);

	while ((s3=index(s1, *s2)) != NULL) {
		if (strncmp(s3, s2, s2len) == 0)
			return (s3);
		s1 = ++s3;
	}
	return (NULL);
}

/*ARGSUSED*/
xerror(d, ev)
Display *d;
register XErrorEvent *ev;
{
    fprintf (stderr, "%s:  warning, error event receieved:\n", xterm_name);
    (void) XmuPrintDefaultErrorMessage (d, ev, stderr);
    Exit (ERROR_XERROR);
}

/*ARGSUSED*/
xioerror(dpy)
Display *dpy;
{
    (void) fprintf (stderr, 
		    "%s:  fatal IO error %d (%s) or KillClient on X server \"%s\"\r\n",
		    xterm_name, errno, SysErrorMsg (errno),
		    DisplayString (dpy));

    Exit(ERROR_XIOERROR);
}

XStrCmp(s1, s2)
char *s1, *s2;
{
  if (s1 && s2) return(strcmp(s1, s2));
  if (s1 && *s1) return(1);
  if (s2 && *s2) return(-1);
  return(0);
}