[comp.sys.dec] Tradeoffs between DEC & MIT servers

de5@de5.CTD.ORNL.GOV (Dave Sill) (09/06/90)

What are the tradeoffs between the DEC UWS server and the MIT R4
server?  I'm considerring switching from the DEC to the MIT because I
want R4 features and don't like DEC's nonstandard font mechanism.  I
realize I'd be loosing Display PostScript--not a big deal to me at
this point--but what about performance?  Are there any other
differences?  Is this a good idea?

-- 
Dave Sill (de5@ornl.gov)
Martin Marietta Energy Systems
Workstation Support

klee@wsl.dec.com (Ken Lee) (09/06/90)

In article <1990Sep6.133417.10252@cs.utk.edu>, de5@de5.CTD.ORNL.GOV (Dave Sill)
writes:
|> I'm considerring switching from the DEC to the MIT because I
|> want R4 features and don't like DEC's nonstandard font mechanism. 

As far as I know, the current DEC servers completely follow the X
protocol and XLFD for all font mechanisms.  They also accept the
standard BDF font formats.  Compiled (binary) file formats may be
different, but there are no standards for these.

Ken Lee
DEC Western Software Laboratory, Palo Alto, Calif.
Internet: klee@wsl.dec.com
uucp: uunet!decwrl!klee

mike@raven.uss.tek.com (Mike Ewan) (09/08/90)

In article <1990Sep6.133417.10252@cs.utk.edu> Dave Sill <de5@ornl.gov> writes:
>What are the tradeoffs between the DEC UWS server and the MIT R4
>server?  I'm considerring switching from the DEC to the MIT because I
>want R4 features and don't like DEC's nonstandard font mechanism.  I
>realize I'd be loosing Display PostScript--not a big deal to me at
>this point--but what about performance?  Are there any other
>differences?  Is this a good idea?


I've used both, although I haven't used the DEC windows server extensively,
and the MIT server/clients are far faster.  Also you get more choices for
window managers and other goodies.

Mike
--
 Michael Ewan    (503)627-6468      Internet:  mike@raven.USS.TEK.COM
 Unix Systems Support                   UUCP:  ...!tektronix!puffin!raven!mike
 Tektronix, Inc.                  Compuserve:  73747,2304
"Fig Newton: The force required to accelerate a fig 39.37 inches/sec."--J. Hart

klee@wsl.dec.com (Ken Lee) (09/08/90)

In article <6524@tekgen.BV.TEK.COM>, mike@raven.uss.tek.com (Mike Ewan) writes:
|> I've used both, although I haven't used the DEC windows server extensively,
|> and the MIT server/clients are far faster.  Also you get more choices for
|> window managers and other goodies.

If you do an objective test, you should find that the current DEC and
MIT servers are roughly equivalent in performance.  Any client,
including window managers, using the standard X11 protocol should work
properly with either server (modulo bugs and font availability).

Ken Lee
DEC Western Software Laboratory, Palo Alto, Calif.
Internet: klee@wsl.dec.com
uucp: uunet!decwrl!klee

steven@pacific.csl.uiuc.edu (Steven Parkes) (09/08/90)

In article <9009080033.AA20488@xenon.lcs.mit.edu>,
keith@EXPO.LCS.MIT.EDU (Keith Packard) writes:

|> The DEC servers for the RISC workstations are faster than MIT R4 for
|> almost all rendering operations; especially with the more recent
|> releases from DEC. 

Related to this, I was wondering if its possible to figure exactly what
/usr/lib/X11/getcons (exec'd by dxsession) does to keep console
messages from being scribbled in the root window.

This information would be useful for two things: 1) to be able to use xdm or
something other that dxsession and 2) to set up a widget for console output
before login so that console messages don't get scribbled into the root in the
period when the login widget (Xprompter, etc.) is active.

Messages can't be read on our monochrome systems (3max) and they are known to
complete confuse the color server (VAXstation 3500) on occasion.

steven parkes ---------------------------------------
University of Illinois Coordinated Science Laboratory
steven@pacific.csl.uiuc.edu -------------------------

meissner@osf.org (Michael Meissner) (09/09/90)

In article <1990Sep8.105509@pacific.csl.uiuc.edu>
steven@pacific.csl.uiuc.edu (Steven Parkes) writes:

| In article <9009080033.AA20488@xenon.lcs.mit.edu>,
| keith@EXPO.LCS.MIT.EDU (Keith Packard) writes:
| 
| |> The DEC servers for the RISC workstations are faster than MIT R4 for
| |> almost all rendering operations; especially with the more recent
| |> releases from DEC. 
| 
| Related to this, I was wondering if its possible to figure exactly what
| /usr/lib/X11/getcons (exec'd by dxsession) does to keep console
| messages from being scribbled in the root window.
| 
| This information would be useful for two things: 1) to be able to use xdm or
| something other that dxsession and 2) to set up a widget for console output
| before login so that console messages don't get scribbled into the root in the
| period when the login widget (Xprompter, etc.) is active.
| 
| Messages can't be read on our monochrome systems (3max) and they are known to
| complete confuse the color server (VAXstation 3500) on occasion.

The short answer is reading /dev/xcons will get the console output,
instead of blitting it to the screen.

I use a hacked version of the X11R4 xconsole contributed software.
Here is the shar of my current changes (it's a complete shar, so you
don't need to get the original).  Earlier versions ran on DECwindows,
but I may have changed things about when I went to X11R4.  You
definately need to define XAW_BC for Athena Widget bug compatibility
mode.

#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./Imakefile`
then
echo "writing ./Imakefile"
cat > ./Imakefile << '\End\Of\Shar\'
#ifdef BandAidCompiler
#include BandAidCompiler
#endif

        DEFINES = -DXAW_BC
        DEPLIBS = XawClientDepLibs
LOCAL_LIBRARIES = XawClientLibs
           SRCS = console.c main.c
           OBJS = console.o main.o

ComplexProgramTarget(xconsole)

InstallAppDefaults(XConsole)
\End\Of\Shar\
else
  echo "will not over write ./Imakefile"
fi
if [ `wc -c ./Imakefile | awk '{printf $1}'` -ne 282 ]
then
echo `wc -c ./Imakefile | awk '{print "Got " $1 ", Expected " 282}'`
fi
if `test ! -s ./Makefile`
then
echo "writing ./Makefile"
cat > ./Makefile << '\End\Of\Shar\'

PROGRAM = xconsole
SOURCES	= console.c main.c
OBJECTS	= console.o main.o
HEADERS	= console.h
CC	= gcc
CFLAGS	= -g -O1 -DXAW_BC
LD	= $(CC)
LDFLAGS	=
LIBS	= -lXaw -lXmu -lXt -lXext -lX11

$(PROGRAM): $(OBJECTS)
	$(LD) -o $(PROGRAM) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(LIBS)

console.o: console.c $(HEADERS)

main.o: main.c $(HEADERS)

clean:
	rm -f $(OBJECTS) core *.out
\End\Of\Shar\
else
  echo "will not over write ./Makefile"
fi
if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 368 ]
then
echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 368}'`
fi
if `test ! -s ./README`
then
echo "writing ./README"
cat > ./README << '\End\Of\Shar\'
The xconsole program displays output directed to /dev/console.

It should be installed suid root, if the signal based protocol for
restarting xconsole is to be used.

Please send comments and bug reports to:

roman@athena.mit.edu
\End\Of\Shar\
else
  echo "will not over write ./README"
fi
if [ `wc -c ./README | awk '{printf $1}'` -ne 230 ]
then
echo `wc -c ./README | awk '{print "Got " $1 ", Expected " 230}'`
fi
if `test ! -s ./XConsole.ad`
then
echo "writing ./XConsole.ad"
cat > ./XConsole.ad << '\End\Of\Shar\'
! ------------------------------------------------------------
!    Resources for the console
! ------------------------------------------------------------
XConsole*consoleLog: /tmp/conslog

XConsole*reverseVideo: true
!
!XConsole*background:    midnightblue
!XConsole*foreground:    sandybrown

!example of disabling the title: uncomment the next line
!XConsole*doTitle: false
!XConsole*title.label: 

!XConsole*title.width: 150
!XConsole*title.borderWidth: 0
XConsole.geometry: -0+0
XConsole*text.width: 487
XConsole*text.height: 200
XConsole*text.displayCaret: false

XConsole*text.horizDistance: 6
XConsole.autoRaise: on

XConsole*text.translations:	#replace \n\
				<Btn1Down>:	select-start() \n\
				<Btn1Motion>:	extend-adjust() \n\
				<Btn1Up>:	extend-end(PRIMARY, CUT_BUFFER0)


XConsole*text*font: fixed
XConsole*text.borderWidth: 1
!XConsole*title.font: -adobe-new century schoolbook-bold-r-normal--18-180-75-75-*
XConsole*thickness: 10

XConsoleFrame.defaultDistance: 1
XConsole*closeWindow.label: Hide
XConsole*closeWindow.borderWidth: 2

XConsole*closeWindow.horizDistance: 452

XConsole*closeWindow.internalHeight: 2
XConsole*closeWindow.font: -adobe-new century schoolbook-bold-r-normal--14-140-75-75-*

XConsole*Command*resize: false

!XConsole*title.top: ChainTop
!XConsole*title.bottom: ChainTop
!XConsole*title.left: ChainLeft
!XConsole*title.right: ChainLeft

XConsole*closeWindow.top: ChainTop
XConsole*closeWindow.bottom: ChainTop
XConsole*closeWindow.left: ChainRight
XConsole*closeWindow.right: ChainRight

XConsole*text.top: ChainTop
XConsole*text.bottom: ChainBottom
XConsole*text.left: ChainLeft
XConsole*text.right: ChainRight

!XConsole*text.fromVert: title

XConsole*displayNonPrinting: false
\End\Of\Shar\
else
  echo "will not over write ./XConsole.ad"
fi
if [ `wc -c ./XConsole.ad | awk '{printf $1}'` -ne 1726 ]
then
echo `wc -c ./XConsole.ad | awk '{print "Got " $1 ", Expected " 1726}'`
fi
if `test ! -s ./console.c`
then
echo "writing ./console.c"
cat > ./console.c << '\End\Of\Shar\'
/*
 *	$Header: /usr/sandboxes/meissner/xconsole/RCS/console.c,v 1.4 90/08/27 10:05:22 meissner Exp Locker: meissner $
 *
 * 	Copyright (C) 1988 Massachusetts Institute of Technology	
 *	
 */


/*

   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 M.I.T. not be used in
   advertising or publicity pertaining to distribution of the
   software without specific, written prior permission.
   M.I.T. makes no representations about the suitability of
   this software for any purpose.  It is provided "as is"
   without express or implied warranty.

*/

/** Author:  Roman J. Budzianowski - Project Athena, MIT **/

#if ( !defined(lint) && !defined(SABER))
static char *rcsid_console_c = "$Header: /usr/sandboxes/meissner/xconsole/RCS/console.c,v 1.4 90/08/27 10:05:22 meissner Exp Locker: meissner $";
#endif lint

#include <stdio.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Label.h>
#include <X11/Shell.h>
#include <X11/Xaw/AsciiText.h>
#include <sys/ioctl.h>
#include <sys/types.h>

#include "console.h"

extern char *ctime ();
extern time_t time ();
extern ConsoleRec theConsole;

static XtCallbackRec callbacks[] = {
   {NULL,NULL},
   {NULL,NULL}
};

/* ARGSUSED */
void CloseWindow(w,closure,call_data)
     Widget w;
     caddr_t closure;
     caddr_t call_data;
{
   Console console = (Console)closure;

   XtPopdown(console->shell);
   console->mapped = False;
   
}

void CreateLogFile(console)
     Console console;
{
   int f;
   int open_flag = O_CREAT|O_TRUNC;

   if(console->retain)
     open_flag = O_RDWR;

   f = open(console->consoleLog,open_flag,0666);
   if(f>=0)
     close(f);
   else
     SystemError("Cannot open console log file.\n");
}

void DestroyConsole(console)
     Console console;
{
   if(console->terminalOutput)
      XtRemoveInput(console->terminalOutput);
   XtDiskSourceDestroy(XtTextGetSource(console->text));
}

void ClearConsole(console)
     Console console;
{
   Arg          args[2];
   extern Boolean dbg;

   Debug("clearing console");
   XtDiskSourceDestroy(XtTextGetSource(console->text));
   
   CreateLogFile(console);
   XtSetArg(args[0],XtNfile,console->consoleLog);
   XtSetArg(args[1],XtNeditType,XttextAppend);
   XtTextSetSource(console->text,
		   XtDiskSourceCreate(console->text, args, 2),(XtTextPosition)0);

   if(dbg)
     return;

   ConsoleDown();

}

static XEvent lastEvent;

/* ARGSUSED */
Bool CheckEvent(dsp,event,arg)
     Display *dsp;
     XEvent *event;
     char *arg;
{
   Debug("CheckEvent: event.type = %d",event->type);

   if(event->type == MapNotify || event->type == UnmapNotify){
      Window win = (Window)arg;
      if(event->xmap.window == win){
	 Debug("CheckEvent: Found !!!");
	 return True;
      }
      else
	return False;
   }
   else
     return False;
}

/* ARGSUSED */
void HandleMap(w, data, event)
     Widget w;
     caddr_t data;
     XEvent *event;
{
   if(event->type == MapNotify || event->type == UnmapNotify){
      Window win = event->xmap.window;

      bcopy((char *)event,(char *)&lastEvent,sizeof(XEvent));

      XSync(XtDisplay(w),0);

      Debug("HandleMap: event.type = %d win = %d",event->type, win);


      if(theConsole.debug){
	 int nevents;
	 nevents = XEventsQueued(XtDisplay(w),QueuedAfterReading);
	 Debug("HandleMap: Events in the queue = %d",nevents);
      }

      while(XCheckIfEvent(XtDisplay(w), &lastEvent, CheckEvent, (char *)win))
	;

      Debug("HandleMap: lastEvent  event.type = %d\n",lastEvent.type);
      if(lastEvent.type == MapNotify){
	 ConsoleUp();
      } else
	if(lastEvent.type == UnmapNotify){
	   ConsoleDown();
	}
   }
}


void CreateConsole(console)
     Console console;
{
   Arg       args[7];
   Widget    frame,text;
   Cardinal  n;

   Debug("creating console.");

   XtAddEventHandler(console->shell,StructureNotifyMask,False,HandleMap,(caddr_t)console);

   frame = XtCreateWidget("consoleFrame", formWidgetClass, console->shell, args, 0);


    /** create title **/
   console->title = (console->doTitle)
       ? XtCreateManagedWidget("title", labelWidgetClass, frame, args, 0)
       : 0;

   callbacks[0].callback = CloseWindow;
   callbacks[0].closure  = (caddr_t)console;
   XtSetArg(args[0],XtNcallback,callbacks);

   console->close = XtCreateManagedWidget("closeWindow", commandWidgetClass, frame, args, 1);

   CreateLogFile(console);

   n = 0;
   XtSetArg(args[n],XtNeditType,XttextAppend);n++;
   XtSetArg(args[n],XtNtextOptions, scrollOnOverflow|scrollVertical|wordBreak);n++;
   XtSetArg(args[n],XtNfile,console->consoleLog);n++;
   text = XtCreateManagedWidget("text", asciiDiskWidgetClass, frame, args, n);
   console->text = text;

   XtManageChild(frame); 
   
   console->mapped = False;

}

void DisableRedisplay()
{
   XtTextDisableRedisplay(theConsole.text);
}

void EnableRedisplay()
{
   XtTextEnableRedisplay(theConsole.text);
}

void InitializeConsole(console)
     Console console;
{
   char name[BUFSIZ], hostname[BUFSIZ];
   Arg args[1];

   if(console->doTitle == False)
     return;

   strcpy(name,"Console  ");
   gethostname(hostname,BUFSIZ);
   strcat(name,hostname);
   strcat(name,":");
   strcat(name,rindex(console->ttydev,'/') + 1);

   XtSetArg(args[0],XtNlabel,name);
   XtSetValues(console->title,args,1);
}

void ConsoleUp()
{
   if(theConsole.mapped == False){
     XtPopup(theConsole.shell ,XtGrabNone);
     theConsole.mapped = True;
  }
}

void ConsoleDown()
{
   if(theConsole.mapped == True){
      XtPopdown(theConsole.shell);
      theConsole.mapped = False;
   }
}

void WriteToConsole(text, ignore_popup)
     char *text;
     Bool ignore_popup;
{
   static XtTextBlock block = { 0, 0, NULL, };
   int status;
   Console console = &theConsole;

   if(theConsole.debug){
     unsigned char *p;
     int ch;

     fprintf (stderr, "Text %s:\t'", ignore_popup ? "t" : "f");
     for (p = (unsigned char *) text; (ch = *p) != '\0'; p++){
       if (ch == '\n')
	 fprintf (stderr, "\\n");
       else if (ch == '\r')
	 fprintf (stderr, "\\r");
       else if (ch == '\t')
	 fprintf (stderr, "\\t");
       else if (ch == '\\')
	 fprintf (stderr, "\\\\");
       else if (ch >= ' ' && ch <= '~')
	 putc (ch, stderr);
       else
	 fprintf (stderr, "\\%.3o", ch);
     }
     fprintf (stderr, "'\n");
     fflush (stderr);
   }

   block.length = strlen(text);
   block.ptr = text;

   status = XtTextReplace(console->text, XtTextGetInsertionPoint(console->text),
			XtTextGetInsertionPoint(console->text), &block);

   if(status != XawEditDone){
      if(status == XawPositionError)
	Debug("Internal error in WriteToConsole:   Position error.");
      else
	Debug("Internal error in WriteToConsole:   Edit error.");
   }

   if(ignore_popup)
     return;

   if(!console->mapped){
      XtPopup(console->shell ,XtGrabNone);
      console->mapped = True;
   }
   else if(console->autoRaise)
     XRaiseWindow(XtDisplay(console->shell),XtWindow(console->shell));

   if (console->ringBell)
     XBell(XtDisplay(console->shell), 0);
}

void HandleAllEvents(w)
     Widget w;
{
   XEvent ev;

   while(XtAppPending(theConsole.appContext)){
      XtAppNextEvent(theConsole.appContext,&ev);
      XtDispatchEvent(&ev);
   }
   XFlush(XtDisplay(w));
}


void PrintTime(skip_date)
     Boolean skip_date;
{
  static char time_buffer[28] = "\n";
  static time_t last_time = 0;
  time_t now = time ((time_t *)0);
    
  if (((unsigned)(now - last_time)) > 5*60 && skip_date == False) {
    strcpy (&time_buffer[1], ctime (&now));
    WriteToConsole(time_buffer, True);
  }
    
  last_time = now;
}


/* ARGSUSED */
void ReadSession(data,src,id)
     caddr_t    data;
     int        *src;
     XtInputId  *id;
{
   static char buffer[BUFSIZ+1];
   static char line[BUFSIZ+1];
   static char *lptr = &line[0];
   static char *lend = &line[BUFSIZ];
   static Boolean skip_date = False;
   char *lstart = lptr;
   int nbytes;
   int i;
   int j;
   int num_unread;

   nbytes = read(*src,buffer,BUFSIZ);
   switch(nbytes){
    case -1:
      SystemWarning("Error when reading pty.");
      XtRemoveInput(*id);
      break;

    case 0:
      Debug("End of file.");
      XtRemoveInput(*id);
      break;

    default:
      for(i = j = 0; i<nbytes; i++) {
	int ch = buffer[i] & 0x7f;
	if(ch == 7)
	  XBell(XtDisplay(theConsole.shell), 0);

	if (ch != '\0' && ch != '\r') {
	  *lptr++ = ch;
	  if (ch == '\n' || lptr == lend) {
	    Bool ignore = False;
	    *lptr = '\0';
	    if (lstart == line && theConsole.printDate)
	      PrintTime(skip_date);

	    if (theConsole.ignoreRegexp != NULL && *theConsole.ignoreRegexp != '\0')
	      {
		ignore = re_exec (line);
		Debug ("Ignore Regexp = %s", ignore ? "True" : "False");
	      }

	    WriteToConsole(lstart, ignore);
	    lptr = lstart = &line[0];
	  }  
	}
      }

      if (lptr != lstart) {
	*lptr = 0;
	if (lstart == line && theConsole.printDate)
	  PrintTime(skip_date);

	WriteToConsole(lstart, True);
      }

      skip_date = (ioctl (*src, FIONREAD, &num_unread) == 0 && num_unread > 0) ? True : False;
      break;
   }
}
\End\Of\Shar\
else
  echo "will not over write ./console.c"
fi
if [ `wc -c ./console.c | awk '{printf $1}'` -ne 9396 ]
then
echo `wc -c ./console.c | awk '{print "Got " $1 ", Expected " 9396}'`
fi
if `test ! -s ./console.h`
then
echo "writing ./console.h"
cat > ./console.h << '\End\Of\Shar\'
/*
 * xconsole
 *
 * $Header: /usr/sandboxes/meissner/xconsole/RCS/console.h,v 1.4 90/08/27 10:05:25 meissner Exp Locker: meissner $
 *
 * Copyright 1988 Massachusetts Institute of Technology
 *
 * 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 M.I.T. not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  M.I.T. makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * Author:    Roman J. Budzianowski
 * Created:   March 27, 1989
 */

#ifndef _CONSOLE
#define _CONSOLE

typedef struct _console {
   XtAppContext appContext;
   Widget    shell;
   Boolean   mapped;
   Widget   title;
   Widget   text;
   Widget   close;
   Boolean  retain;		/* retain existing log ? */
   Boolean  doTitle;		/* display title ?  */
   char     *consoleLog;
   XtInputId terminalOutput;
   Boolean  autoRaise;
   char     *ttydev;
   int      pty;
   Boolean  debug;
   Boolean  ringBell;		/* ring bell on new messages */
   Boolean  printDate;		/* print date/time before messages */
   char	    *ignoreRegexp;	/* no popup and/or bell if match regexp */
} ConsoleRec, *Console;

void WriteToConsole(), CreateConsole();
void ClearConsole();
void DestroyConsole();
void ReadSession();
void ScrollUp();
void ScrollTo();
void ConsoleUp();
void ConsoleDown();
void HandleAllEvents();

#include <X11/Xaw/Text.h>
XtTextPosition GetPosition();
#endif _CONSOLE
\End\Of\Shar\
else
  echo "will not over write ./console.h"
fi
if [ `wc -c ./console.h | awk '{printf $1}'` -ne 1795 ]
then
echo `wc -c ./console.h | awk '{print "Got " $1 ", Expected " 1795}'`
fi
if `test ! -s ./main.c`
then
echo "writing ./main.c"
cat > ./main.c << '\End\Of\Shar\'
/*
 * xconsole
 *
 * $Header: /usr/sandboxes/meissner/xconsole/RCS/main.c,v 1.4 90/08/27 10:04:29 meissner Exp Locker: meissner $
 *
 * Copyright 1988 Massachusetts Institute of Technology
 *
 * 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 M.I.T. not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  M.I.T. makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * Author:   Roman J. Budzianowski 
 * Created:  July 17 1989
 */

#if ( !defined(lint) && !defined(SABER))
  static char rcs_version[] = "$Header: /usr/sandboxes/meissner/xconsole/RCS/main.c,v 1.4 90/08/27 10:04:29 meissner Exp Locker: meissner $";
#endif


#include <stdio.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xatom.h>
#include <X11/Shell.h>
#include <syslog.h>
#include <signal.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/types.h>

#include "console.h"

void SetupTTY();
static void error_status();
static void AbortOtherConsole();
void UnRegisterXcons();
void PrintUsage();
char *getenv();
char *re_comp();

static XtResource console_resources[] = {
   {"mapped", "Mapped", XtRBoolean, sizeof(Boolean),
      XtOffset(Console,mapped), XtRString, "true"},
   {"debug", "Debug", XtRBoolean, sizeof(Boolean),
      XtOffset(Console,debug), XtRString, "false"},
   {"autoRaise", "AutoRaise", XtRBoolean, sizeof(Boolean),
      XtOffset(Console,autoRaise), XtRString, "true"},
   {"retain", "Retain", XtRBoolean, sizeof(Boolean),
      XtOffset(Console,retain), XtRString, "false"},
   {"doTitle", "DoTitle", XtRBoolean, sizeof(Boolean),
      XtOffset(Console,doTitle), XtRString, "true"},
   {"consoleLog", "ConsoleLog", XtRString, sizeof(String),
      XtOffset(Console,consoleLog), XtRString, "/tmp/console.log"},
   {"ringBell", "RingBell", XtRBoolean, sizeof(Boolean),
      XtOffset(Console,ringBell), XtRBoolean, "false"},
   {"printDate", "PrintDate", XtRBoolean, sizeof(Boolean),
      XtOffset(Console,printDate), XtRBoolean, "false"},
   {"ignoreRegexp", "IgnoreRegexp", XtRString, sizeof(String),
      XtOffset(Console,ignoreRegexp), XtRString, NULL},
};

XrmOptionDescRec command_line_options[] = {
   {"-retain",   "retain",       XrmoptionNoArg,  (caddr_t) "true" },
   {"-log",      "consoleLog",   XrmoptionSepArg, (caddr_t) NULL },
   {"-debug",    "debug",        XrmoptionNoArg,  (caddr_t) "true" },
   {"-unmapped", "mapped",       XrmoptionNoArg,  (caddr_t) "false" },
   {"-bell",	 "ringBell",	 XrmoptionNoArg,  (caddr_t) "true" },
   {"-date",	 "printDate",	 XrmoptionNoArg,  (caddr_t) "true" },
   {"-ignore",	 "ignoreRegexp", XrmoptionSepArg, (caddr_t) NULL },
};

static struct Xcons_args {
  char * name;			/* name of the argument. */
  char * param;			/* parameter it takes. */
  char * description;		/* description of it. */
} xcons_args[] = {
   {"-retain",   "",			"retain log of the old console"},
   {"-log",      "<log file>",		"file to log the console output"},
   {"-unmapped", "",			"start the console in unmapped state"},
   {"-xrm",	 "<resource name>",	"Allows resource specification."},
   {"-bell",	 "",			"Ring bell for new messages."},
   {"-date",	 "",			"Print time/date if last message > 5 minutes old."},
   {"ignore",	 "<regexp>",		"Don't popup or ring bell if line matches regexp."},
   {NULL,	 NULL,			NULL },
};

ConsoleRec theConsole;
#define XCONSLOCK "/tmp/xconslock"

Boolean dbg = False;
Boolean debugging = False;
Boolean exiting = False;
Boolean dispatching = False;

/* create a pipe and register one end of it as an input source with the toolkit
   I heard this idea from Ralph Swick - modifying XtNextEvent to call a function when
   select returns because of signal would be better, but...*/
int signalpipe[2];

/* ARGSUSED */
void HandleSignal(data,src,id)
     caddr_t    data;
     int        *src;
     XtInputId  *id;
{
   Debug("HandleSignal: got signal");
   if(exiting)
     UnRegisterXcons(&theConsole);
}

void KillExit(sig)
{
  extern char *sys_siglist[];
  char byte = 1;
  char buffer[200];
  if (dbg) {
    sprintf (buffer, "xlogin killed by signal %d [%s]", sig, sys_siglist[sig]);
    SystemNotice(buffer);
  }

  exiting = True;
  write(signalpipe[1],&byte,1);
}


void main(argc,argv)
     int argc;
     char **argv;
{
   Display *dpy;
   Arg args[10];
   char *resdir;
   XrmDatabase xconsoleDB = NULL;

   setuid(0);

   signal(SIGTERM, KillExit);
   signal(SIGHUP, KillExit);
   signal(SIGINT, KillExit);

   umask(0);

   /* Start the toolkit */

   XtToolkitInitialize();

   theConsole.appContext = XtCreateApplicationContext();

   dpy =  XtOpenDisplay(theConsole.appContext, NULL, argv[0], "XConsole",
			command_line_options, XtNumber(command_line_options),
			&argc, argv);

   theConsole.shell = XtAppCreateShell(argv[0],"XConsole", applicationShellWidgetClass,
                               dpy, args, 0);

   XtGetApplicationResources(theConsole.shell, &theConsole, 
			     console_resources, XtNumber(console_resources),
			     (ArgList)NULL, (Cardinal)0);

   if(argc != 1)
     PrintUsage();
			     
   if (theConsole.ignoreRegexp != NULL && *theConsole.ignoreRegexp != '\0')
     {
       char *msg = re_comp (theConsole.ignoreRegexp);
       if (msg != NULL)
	 {
	   fputs (msg, stderr);
	   theConsole.ignoreRegexp = 0;
	 }
     }

   if(theConsole.debug == True)
     dbg = True;

   if(theConsole.mapped == False)
     XtSetMappedWhenManaged(theConsole.shell,False);

   AbortOtherConsole(&theConsole);
     
   CreateConsole(&theConsole);

   SetupTTY(&theConsole);

   InitializeConsole(&theConsole);

   XtRealizeWidget(theConsole.shell);

   if(pipe(signalpipe)==0)
     XtAppAddInput(theConsole.appContext,signalpipe[0],XtInputReadMask,HandleSignal,NULL);
   else
     SystemError("xconsole: cannot create pipe for signal handling");
     
   if(exiting)
     UnRegisterXcons(&theConsole);
   while(1){
      XEvent ev;
      XtAppNextEvent(theConsole.appContext,&ev);
      XtDispatchEvent(&ev);
   }
}

void UnRegisterXcons(console)
     Console console;
{
   DestroyConsole(console);
   /*need to close pty ? */
   close(console->pty);
   /* tty ? */

   Debug("Xconsole: exiting killed by signal");
   exit(0);
}


static void AbortOtherConsole(console)
     Console console;
{
   int lock = -1;
   int pid;
   int ret;

   /* check if another console is running */
   if(access(XCONSLOCK,R_OK|W_OK) == -1){ /* for whatever reason cannot stat lock file */
      Debug("Cannot stat lock file");
      goto setlock;
   }

   lock = open(XCONSLOCK,O_RDWR,0);
   if(lock < 0){
      Debug("Cannot open lock file");
      goto setlock;
   }
   
   ret = read(lock,&pid,sizeof(int));
   
   if(ret != sizeof(int)){	/* couldn't get pid of the other console */
      Debug("Cannot get pid");
      goto setlock;
   } 
   
   /* kill the other guy */
   if(kill(pid, 0) == 0 && kill(pid,SIGTERM) == -1){
      Debug("Cannot kill other console");
      goto setlock;
   }

   /* retrieve the log file name */
   if(console->retain){
      char buf[BUFSIZ];
      ret = read(lock,buf,BUFSIZ);
      if(ret > 0){
	 buf[ret] = '\0';
	 if(strcmp(buf,console->consoleLog)){
	    char copy[BUFSIZ];
	    sprintf(copy, "cp %s %s",buf, console->consoleLog);
	    if(system(copy)){
	       XtWarning("Cannot copy console log");
	       console->retain = False;
	    }
	 }
      } else
	console->retain = False;
      
      Debug("retain: %s - %s",(console->retain)? "Yes" : "No", console->consoleLog);
   }
   
 setlock:
   error_status();
   if(lock >= 0)
     close(lock);

   lock = open(XCONSLOCK,O_RDWR|O_TRUNC|O_CREAT,0666);
   
   if(lock < 0)
     SystemError("XCons: Cannot open lock file, exiting...");

/*   lseek(lock,(off_t)0,L_SET);*/

   pid = getpid();
   write(lock,&pid,sizeof(int));
   write(lock,console->consoleLog,strlen(console->consoleLog));
   close(lock);
   
   return;
}

   
#define DEVSIZE 16
static char ptydev[DEVSIZE] , ttydev[DEVSIZE];

void SetupTTY(console)
     Console console;
{
  int devconsole,ttyconsole;
  int on = 1;
  int status = -1;

  strcpy(ptydev,"/dev/");
  strcpy(ttydev,"/dev/");

  Debug("opening console");

#ifdef ultrix
  if (!debugging) {
     if ((devconsole = open("/dev/xcons", O_RDONLY, 0)) < 0) {
	String str = "xconsole:Couldn't open /dev/xcons";
	SystemNotice(str);
	XtError(str);
     }
     console->terminalOutput =
       XtAppAddInput(console->appContext, devconsole, XtInputReadMask,
		     ReadSession, NULL);
     console->ttydev = "/dev/xcons";
     console->pty = devconsole;
  }
#else /*ultrix*/

  Debug("looking for a good pty/tty");
  status = get_pty(&devconsole,&ttyconsole);

  if(status >= 0){
     console->ttydev = ttydev;
     console->pty = devconsole;	/* pty */

     Debug("pty = %d tty= %d",devconsole,ttyconsole);

#ifdef TIOCCONS
     if(debugging == False)
       if (ioctl(devconsole, TIOCCONS, (char *)&on) == -1){
	  SystemWarning("Couldn't get console output");
	  return;
       }
#else
     /* here are implementation for other systems*/
     SystemNotice("xconsole:Couldn't grab console");
     XtError("Couldn't grab console");
#endif

     console->terminalOutput = XtAppAddInput(console->appContext,devconsole,XtInputReadMask,
						ReadSession,NULL);
  }
  else {
     SystemError("Couldn't find good pty");
     exit(1);
  }
#endif /*ultrix*/

  if(dbg == False){

  }

}


get_pty(pty,tty)
     int *pty,*tty;
{
   int status;
   
   strcpy(ptydev,"/dev/ptyp0");
   strcpy(ttydev,"/dev/ttyp0");

   /*********** we try only once !!!! ***********/
   status = try_last(ptydev,pty);

   if(status == 0){
      Debug("pty: %s ",ptydev);
      return(*tty=do_open(ptydev,ttydev));
   }
   else{
      ptydev[8] = 'q';
      ptydev[9] = '0';
      status = try_last(ptydev,pty);
      if(status == 0){
	 Debug("pty: %s, %s ",ptydev, ttydev);
	 return(*tty=do_open(ptydev,ttydev));
      }
      else
	return -1;
   }
}

do_open(ptydev,ttydev)
     char ptydev[],ttydev[];
{
   int tty;
   ttydev[8] = ptydev[8];
   ttydev[9] = ptydev[9];
   tty = open(ttydev, O_RDWR,0622);
   return tty;
}

try_last(ptydev,pty)
     char ptydev[];
     int *pty;
{
   int i;
   for(i=0;i<16;i++){
      *pty=open(ptydev, O_RDWR,0622);
      if(*pty >= 0)
	return 0;
      (ptydev[9])++;
   }
   return -1;
}

extern int errno;
extern int sys_nerr;
extern *sys_errlist[];

static void error_status()
{
   if( errno > 0 && errno <= sys_nerr){
      syslog(LOG_WARNING, sys_errlist[errno]);
      Debug("System error: %s.",sys_errlist[errno]);
   }
}

SystemError(string)
     char *string;
{
   syslog(LOG_NOTICE, string);
   Debug(string);
   error_status();
   exit(1);
}

SystemWarning(string)
     char *string;
{
   error_status();
   syslog(LOG_WARNING, string);
}

SystemNotice(string)
     char *string;
{
   error_status();
   syslog(LOG_NOTICE, string);
}

/*VARARGS1*/
Debug (fmt, arg1, arg2, arg3, arg4, arg5)
char	*fmt;
int	arg1, arg2, arg3, arg4, arg5;
{
	if (dbg) {
	   fprintf(stderr,"Debug:\t");
	   fprintf (stderr,fmt, arg1, arg2, arg3, arg4, arg5);
	   fprintf(stderr,"\n");
	   fflush(stderr);
	}
}

void
PrintUsage()
{
  int i;

  fprintf(stderr, "usage: xconsole [options].\n");
  
  for (i = 0 ; xcons_args[i].name != NULL; i++)
    fprintf(stderr, "%-10s %-20s %s\n", xcons_args[i].name, 
	    xcons_args[i].param, xcons_args[i].description);
  exit(1);
}
\End\Of\Shar\
else
  echo "will not over write ./main.c"
fi
if [ `wc -c ./main.c | awk '{printf $1}'` -ne 11783 ]
then
echo `wc -c ./main.c | awk '{print "Got " $1 ", Expected " 11783}'`
fi
if `test ! -s ./mrm.defaults`
then
echo "writing ./mrm.defaults"
cat > ./mrm.defaults << '\End\Of\Shar\'
!
! XConsole
!
XConsole.consoleLog:			/tmp/conslog
XConsole.debug:				false
XConsole.ringBell:			true
XConsole.printDate:			true
XConsole.autoRaise:			on
XConsole.geometry:			+500+174
XConsole.doTitle:			false
XConsole.mapped:			false

XConsole*title.font:			-adobe-new century schoolbook-bold-r-normal--18-180-75-75-*
XConsole*title.label:			Console
XConsole*title.width:			150
XConsole*title.borderWidth:		0
XConsole*title.top:			ChainTop
XConsole*title.bottom:			ChainTop
XConsole*title.left:			ChainLeft
XConsole*title.right:			ChainLeft

XConsole*text*font:			fixed
XConsole*text.borderWidth:		1
XConsole*text.width:			487
XConsole*text.height:			200
XConsole*text.displayCaret:		true
XConsole*text.horizDistance:		6
XConsole*text.top:			ChainTop
XConsole*text.bottom:			ChainBottom
XConsole*text.left:			ChainLeft
XConsole*text.right:			ChainRight
XConsole*text.translations:		#replace \n\
					<Btn1Down>:	select-start() \n\
					<Btn1Motion>:	extend-adjust() \n\
					<Btn1Up>:	extend-end(PRIMARY, CUT_BUFFER0)


XConsole*thickness:			10
XConsole*Frame.defaultDistance:		1

XConsole*closeWindow.label:		Hide
XConsole*closeWindow.borderWidth:	2
XConsole*closeWindow.horizDistance:	452
XConsole*closeWindow.internalHeight:	2
XConsole*closeWindow.font:		-adobe-new century schoolbook-bold-r-normal--14-140-75-75-*
XConsole*closeWindow.top:		ChainTop
XConsole*closeWindow.bottom:		ChainTop
XConsole*closeWindow.left:		ChainRight
XConsole*closeWindow.right:		ChainRight

XConsole*Command*resize:		false
XConsole*displayNonPrinting:		false
\End\Of\Shar\
else
  echo "will not over write ./mrm.defaults"
fi
if [ `wc -c ./mrm.defaults | awk '{printf $1}'` -ne 1542 ]
then
echo `wc -c ./mrm.defaults | awk '{print "Got " $1 ", Expected " 1542}'`
fi
echo "Finished archive 1 of 1"
exit
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

Do apple growers tell their kids money doesn't grow on bushes?

iglesias@orion.oac.uci.edu (Mike Iglesias) (09/09/90)

In article <MEISSNER.90Sep8225817@osf.osf.org> meissner@osf.org (Michael Meissner) writes:
> [... stuff deleted ...]
>I use a hacked version of the X11R4 xconsole contributed software.
>Here is the shar of my current changes (it's a complete shar, so you
>don't need to get the original).  Earlier versions ran on DECwindows,
>but I may have changed things about when I went to X11R4.  You
>definately need to define XAW_BC for Athena Widget bug compatibility
>mode.

I'm curious why you needed to hack xconsole.  I'm using it straight
from the the R4 sources on DECstations running Ultrix 3.0/3.1/4.0
with no problems, althought I'm not using getcons.


Mike Iglesias
University of California, Irvine
Internet:    iglesias@orion.oac.uci.edu
BITNET:      iglesias@uci
uucp:        ...!ucbvax!ucivax!iglesias

meissner@osf.org (Michael Meissner) (09/10/90)

In article <26E9DDD7.8886@orion.oac.uci.edu>
iglesias@orion.oac.uci.edu (Mike Iglesias) writes:

| In article <MEISSNER.90Sep8225817@osf.osf.org> meissner@osf.org (Michael Meissner) writes:
| > [... stuff deleted ...]
| >I use a hacked version of the X11R4 xconsole contributed software.
| >Here is the shar of my current changes (it's a complete shar, so you
| >don't need to get the original).  Earlier versions ran on DECwindows,
| >but I may have changed things about when I went to X11R4.  You
| >definately need to define XAW_BC for Athena Widget bug compatibility
| >mode.
| 
| I'm curious why you needed to hack xconsole.  I'm using it straight
| from the the R4 sources on DECstations running Ultrix 3.0/3.1/4.0
| with no problems, althought I'm not using getcons.

Because I added some features.

    1)	I added an option to ignore lines matching a regexp.
    2)	I completely skip \r in messages (I hate the ^M that comes up)
    3)	I added an option to print the message date if the message is
	more than 5 minutes older than the previous message.
    4)	I added an option to ring the bell when getting a new message.
    5)	I fixed where somebody's mail/news agent split some long lines.
    6)	I made it work with the Ultrix include files before I moved to R4.
    7)	I made ^G's in the output ring the bell.
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

Do apple growers tell their kids money doesn't grow on bushes?

graham@fuel.dec.com (kris graham) (09/11/90)

> I've used both, although I haven't used the DEC windows server extensively,
> and the MIT server/clients are far faster.  

Do you have any data for us to look at?

>Also you get more choices for window managers and other goodies.

I am trying hard to see the relationship between the above and the
base  question...ie...server performance comparisons.  Many
(including me) have tested several MIT clients against Digital
servers, and they work pretty well.   I don't get your point.....
help me out.

Christopher Graham
Internet: graham@fuel.enet.dec.com 
UUCP:     ...!decwrl!fuel.enet.dec.com!graham