*** Imakefile	Sun Jul  5 22:31:49 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/Imakefile	Thu Feb 25 08:25:23 1993
***************
*** 8,22 ****
   */
  
                CC = cc
!        XMINCLUDE = -I/usr/bs/motif/include
!            XMLIB = -L/usr/bs/motif/lib -lXm
! /* -D_NO_PROTO is required for non-ansi compilers */
        EXTRA_DEFS = -D_NO_PROTO
       CDEBUGFLAGS = -O $(EXTRA_DEFS)
    EXTRA_INCLUDES = $(XMINCLUDE)
  /* CONFIG: add str.c str.o if you don't have strdup or strstr */
-             SRCS = connect.c metaserver.c mesg.c popen.c xnetrekm.c 
-             OBJS = connect.o metaserver.o mesg.o popen.o xnetrekm.o
  
  NormalProgramTarget(xnetrekm,$(OBJS), ,$(XMLIB) $(XTOOLLIB) $(XLIB),)
! /* DependTarget($(SRCS)) */
--- 8,32 ----
   */
  
                CC = cc
!        XMINCLUDE = -I/usr/bs/motif-1.2/include
!            XMLIB = -L/usr/bs/motif-1.2/lib -lXm
! /* This might be needed for X11R4 */
! /*       XTOOLIB = -L/usr/bs/motif-1.2/lib -lXt */
! 
! /* CONFIG:
! /* -D_NO_PROTO  	-- needed for motif and non-ansi compilers */
! /* -DGATEWAY		-- for use with gateway */
! /* -DSYSV		-- sysv rather then bsd */
! /* -DXtPointer=char*	-- if your version of X doesn't have XtPointer */
! 
        EXTRA_DEFS = -D_NO_PROTO
       CDEBUGFLAGS = -O $(EXTRA_DEFS)
    EXTRA_INCLUDES = $(XMINCLUDE)
+ 
  /* CONFIG: add str.c str.o if you don't have strdup or strstr */
  
+             SRCS = connect.c metaserver.c mesg.c popen.c strutil.c xnetrekm.c 
+             OBJS = connect.o metaserver.o mesg.o popen.o strutil.o xnetrekm.o
+ 
  NormalProgramTarget(xnetrekm,$(OBJS), ,$(XMLIB) $(XTOOLLIB) $(XLIB),)
! DependTarget($(SRCS))
*** Manifest	Wed Apr 14 12:02:55 1993
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/Manifest	Wed Apr 14 12:20:21 1993
***************
*** 0 ****
--- 1,14 ----
+ Imakefile
+ Makefile
+ Manifest
+ README
+ connect.c
+ mesg.c
+ metaserver.c
+ patchlevel.h
+ popen.c
+ str.c
+ strutil.c
+ xnetrekm.SAMPLE.ad
+ xnetrekm.c
+ xnetrekm.h
*** README	Sun Jul  5 22:17:54 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/README	Wed Apr 14 12:23:45 1993
***************
*** 41,48 ****
        If your system doesn't have strdup() or strstr() add str.c and str.o to
        SRCS & OBJS, respectively.
     2) 'xmkmf'           (or the appropriate imake command)
!    3) 'make'
!    4) './xnetrekm'
  
  
  X CONFIGURABLE RESOURCES
--- 41,50 ----
        If your system doesn't have strdup() or strstr() add str.c and str.o to
        SRCS & OBJS, respectively.
     2) 'xmkmf'           (or the appropriate imake command)
!    3) Check and/or change the symbols in xnetrekm.h for default metaserver,
!       default binary, and location of the ping program.
!    4) 'make'
!    5) './xnetrekm'
  
  
  X CONFIGURABLE RESOURCES
***************
*** 52,65 ****
     after you add/change anything).  The default values are shown here.
     See xnetrekm.SAMPLE.ad for examples.
  
     MetaServerList contains any number of <server> <portnumber> pairs.
  
!    xnetrekm.metaServerList:		sickdog.cs.berkeley.edu 2502
  
     MetaServerTimeout specifies number of seconds before xnetrekm assumes the 
     metaserver is unreachable or down.
  
!    xnetrekm.metaServerTimeout:		10
  
     NetrekBinary describes the default client to execute when a server button
     is pressed.  A full path name may be specified although your PATH shell
--- 54,69 ----
     after you add/change anything).  The default values are shown here.
     See xnetrekm.SAMPLE.ad for examples.
  
+ xnetrekm.metaServerList:		charon.amdahl.com 3520
+ 
     MetaServerList contains any number of <server> <portnumber> pairs.
  
! xnetrekm.metaServerTimeout:		10
  
     MetaServerTimeout specifies number of seconds before xnetrekm assumes the 
     metaserver is unreachable or down.
  
! xnetrekm.netrekBinary:		netrek
  
     NetrekBinary describes the default client to execute when a server button
     is pressed.  A full path name may be specified although your PATH shell
***************
*** 66,105 ****
     variable will be used if not.  This may be overridden by netrekBinaryMap or 
     cyborgBinaryMap.
  
!    xnetrekm.netrekBinary:		netrek
  
     ShowZero indicates whether entries should be displayed for servers with
     0 players.  There is also a toggle button on the display for this feature.
  
!    xnetrekm.showZero:			False
  
     PingProgram contains the location of the network 'ping' program.
  
!    xnetrekm.pingProgram:		/usr/etc/ping
  
     PingSize defines the size of the ping packets.
  
!    xnetrekm.pingSize:			32
  
     NumPings defines the number of pings sent before returning the min/avg/max
     roundtrip times.
  
-    xnetrekm.numPings:			4
- 
     XtrekrcMap contains a list of pairs of the form <server> <xtrekrc>. 
     Clients started on servers matched from this list will use the '-r' flag
!    to specify the xtrekrc file given.  For example:  
     
!    xnetrekm.xtrekrcMap:	calvin.usc.edu ~/.xtrekrc-calvin \
! 			bronco.ece.cmu.edu ~/.xtrekrc-bronco 
!    
     NetrekBinaryMap contains a list of pairs of the form <server> <binary>.
     The client binary specified will be used to connect to that server.
-    For example: 
-    
-    xnetrekm.netrekBinaryMap:	calvin.usc.edu netrek.usc \
- 				legend.cma.fr ~/netrek/fr/x11netrek.Sun4.OS4.1
  
     UseCyborg indicates whether or not the values found in CyborgBinaryMap
     and CyborgXtrekrcMap (if they exist) will be used instead of 
     NetrekBinaryMap and XtrekrcMap.  Typically, this doesn't need to be 
--- 70,108 ----
     variable will be used if not.  This may be overridden by netrekBinaryMap or 
     cyborgBinaryMap.
  
! xnetrekm.showZero:			False
  
     ShowZero indicates whether entries should be displayed for servers with
     0 players.  There is also a toggle button on the display for this feature.
  
! xnetrekm.pingProgram:		/usr/etc/ping
  
     PingProgram contains the location of the network 'ping' program.
  
! xnetrekm.pingSize:			32
  
     PingSize defines the size of the ping packets.
  
! xnetrekm.numPings:			4
  
     NumPings defines the number of pings sent before returning the min/avg/max
     roundtrip times.
+    
+ xnetrekm.xtrekrcMap:	calvin.usc.edu ~/.xtrekrc-calvin \
+ 			bronco.ece.cmu.edu ~/.xtrekrc-bronco 
  
     XtrekrcMap contains a list of pairs of the form <server> <xtrekrc>. 
     Clients started on servers matched from this list will use the '-r' flag
!    to specify the xtrekrc file given.
     
! xnetrekm.netrekBinaryMap:	calvin.usc.edu netrek.usc \
! 				legend.cma.fr ~/netrek/fr/x11netrek.Sun4.OS4.1
! 
     NetrekBinaryMap contains a list of pairs of the form <server> <binary>.
     The client binary specified will be used to connect to that server.
  
+ xnetrekm.useCyborg:		False
+ 
     UseCyborg indicates whether or not the values found in CyborgBinaryMap
     and CyborgXtrekrcMap (if they exist) will be used instead of 
     NetrekBinaryMap and XtrekrcMap.  Typically, this doesn't need to be 
***************
*** 106,145 ****
     specified in your defaults since there is a toggle button on the display 
     for this option.
  
!    xnetrekm.useCyborg:		False
  
     CyborgBinaryMap contains a list of pairs of the form <server> <binary>.
     The client binary specified will be used to connect to that server.
     It is only examined only if the value of useCyborg is true (useCyborg would
     most commonly be set by the toggle button on the display).
-    For example:
- 
-    xnetrekm.cyborgBinaryMap	128.2.209.169	~/borgs/helixborg.sun4
     (Notice that this example gives the numeric address of rwd4.mach.cs.cmu
      since the sun4 version of the helixborg does not handle symbolic names.)
  
     CyborgXtrekrcMap contains a list of pairs of the form <server> <xtrekrc>.
     It is only examined if the value of useCyborg is true (this would most
     commonly be set by the toggle button on the display).  Clients started 
     on servers matched from this list will use the '-r' flag to specify the 
!    xtrekrc file given.  For example:  
  
!    xnetrekm.cyborgXtrekrcMap:	128.2.209.169	~/.xtrekrc-helix
  
     ServerList is a fallback resource that can be used if the metaserver
     is down, or to access servers not listed by the metaserver. It is composed
     of <server> <port> pairs and is only used if the value of useServerList
     is true (most commonly set by the toggle button on the display).  
-    For example:
  
!    xnetrekm.serverList:		doorstop.design.iastate.edu 2592 \
! 				cheetah.cse.csulb.edu 2592
  
     UseServerList indicates whether or not the values found in ServerList
     should be used instead of a query to the metaserver at startup.  There is 
     also a toggle button on the display for this option.
  
!    xnetrekm.useServerList:	False
  
     ServerAddressMap can be used to map servers to inet addresses (if you 
     do not have a name server) or to force a connection to a particular address
--- 109,147 ----
     specified in your defaults since there is a toggle button on the display 
     for this option.
  
! xnetrekm.cyborgBinaryMap	128.2.209.169	~/borgs/helixborg.sun4
  
     CyborgBinaryMap contains a list of pairs of the form <server> <binary>.
     The client binary specified will be used to connect to that server.
     It is only examined only if the value of useCyborg is true (useCyborg would
     most commonly be set by the toggle button on the display).
     (Notice that this example gives the numeric address of rwd4.mach.cs.cmu
      since the sun4 version of the helixborg does not handle symbolic names.)
  
+ xnetrekm.cyborgXtrekrcMap:	128.2.209.169	~/.xtrekrc-helix
+ 
     CyborgXtrekrcMap contains a list of pairs of the form <server> <xtrekrc>.
     It is only examined if the value of useCyborg is true (this would most
     commonly be set by the toggle button on the display).  Clients started 
     on servers matched from this list will use the '-r' flag to specify the 
!    xtrekrc file given.
!    For example:
  
! xnetrekm.serverList:		doorstop.design.iastate.edu 2592 \
! 				cheetah.cse.csulb.edu 2592
  
     ServerList is a fallback resource that can be used if the metaserver
     is down, or to access servers not listed by the metaserver. It is composed
     of <server> <port> pairs and is only used if the value of useServerList
     is true (most commonly set by the toggle button on the display).  
  
! xnetrekm.useServerList:	False
  
     UseServerList indicates whether or not the values found in ServerList
     should be used instead of a query to the metaserver at startup.  There is 
     also a toggle button on the display for this option.
  
! xnetrekm.serverAddressMap:	calvin.usc.edu	128.125.253.129
  
     ServerAddressMap can be used to map servers to inet addresses (if you 
     do not have a name server) or to force a connection to a particular address
***************
*** 146,163 ****
     of a multiple-address server (for example, UDP only seems to work to
     calvin.usc.edu's 128.125.253.129 address for many sites).
  
!    xnetrekm.serverAddressMap:	calvin.usc.edu	128.125.253.129
  
  
  SOURCE
  
     anonymous ftp to cad.ics.uci.edu: /pub/netrek/xnetrekm1.0.tar.Z
                  or pittslug.sug.org: /pub/netrek/xnetrekm1.0.tar.Z
  
  
  TODO
     
!    Athena widgets interface ... ack. 
     
     Currently, output from the netrek clients and error messages are sent
     to the shell window that started the xnetrekm program.  Eventually
--- 148,184 ----
     of a multiple-address server (for example, UDP only seems to work to
     calvin.usc.edu's 128.125.253.129 address for many sites).
  
! xnetrekm.preferredServerList:   bronco.ece.cmu.edu \
!                                 calvin.usc.edu \
!                                 doorstop.design.iastate.edu \
!                                 guzzler.ecst.csuchico.edu \
!                                 legend.cma.fr
  
+    Servers that appear in PreferredServerList will be displayed first
+    if the metaserver indicates that they are active.
  
+ xnetrekm.refreshOnDeiconify:	True
+ 
+    RefreshOnDeiconfiy tells the program to automatically query the
+    metaserver on deiconify _if_ the time specified by minAutoRefresh
+    has elasped.
+ 
+ xnetrekm.minAutoRefresh:	15
+    
+    MinAutoRefresh gives the interval in minutes to wait before automically
+    querying the metaserver if the window has just been deiconified.
+ 
+ 
  SOURCE
  
     anonymous ftp to cad.ics.uci.edu: /pub/netrek/xnetrekm1.0.tar.Z
+ 						 xnetrekm1.0-1.1.patch.Z
                  or pittslug.sug.org: /pub/netrek/xnetrekm1.0.tar.Z
  
  
  TODO
     
!    Athena widgets interface 
     
     Currently, output from the netrek clients and error messages are sent
     to the shell window that started the xnetrekm program.  Eventually
*** connect.c	Mon Jul  6 11:33:37 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/connect.c	Tue Aug  4 00:31:58 1992
***************
*** 1,6 ****
  #include <stdio.h>
  #include <ctype.h>
- #include <time.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <sys/wait.h>
--- 1,5 ----
***************
*** 15,35 ****
  
  #include "xnetrekm.h"
  
- #define NOERROR		0
- #define PARSEERROR	1
- 
  extern Resources	_localRes;
  extern Globals		_globals;
  
! extern void		message(),
! 			error();
! 
! extern char		*strdup();
! 
! char	*findEntry();
! char 	*getNumeric();
! 
! void startNetrek(e)
     
     ServerList	*e;
  {
--- 14,24 ----
  
  #include "xnetrekm.h"
  
  extern Resources	_localRes;
  extern Globals		_globals;
  
! void 
! startNetrek(e)
     
     ServerList	*e;
  {
***************
*** 42,48 ****
  
     /* find server address if specified */
     server_addr = findEntry(e->server, _localRes.serveraddress_map, &err);
!    if(err == PARSEERROR){
        error("Parse error in serverAddressMap resource.\nFormat should be <server> <inet address> ...");
        return;
     }
--- 31,37 ----
  
     /* find server address if specified */
     server_addr = findEntry(e->server, _localRes.serveraddress_map, &err);
!    if(err){
        error("Parse error in serverAddressMap resource.\nFormat should be <server> <inet address> ...");
        return;
     }
***************
*** 57,63 ****
     if(_localRes.use_borg){
     /* find binary */
        binary = findEntry(e->server, _localRes.borgbinary_map, &err);
!       if(err == PARSEERROR){
  	 error("Parse error in cyborgBinaryMap resource.\nFormat should be <server> <binary name> ...");
  	 return;
        }
--- 46,52 ----
     if(_localRes.use_borg){
     /* find binary */
        binary = findEntry(e->server, _localRes.borgbinary_map, &err);
!       if(err){
  	 error("Parse error in cyborgBinaryMap resource.\nFormat should be <server> <binary name> ...");
  	 return;
        }
***************
*** 72,78 ****
  
     if(!binary){
        binary = findEntry(e->server, _localRes.netrekbinary_map, &err);
!       if(err == PARSEERROR){
  	 error("Parse error in netrekBinaryMap resource.\nFormat should be: <server> <binary name> ...");
  	 return;
        }
--- 61,67 ----
  
     if(!binary){
        binary = findEntry(e->server, _localRes.netrekbinary_map, &err);
!       if(err){
  	 error("Parse error in netrekBinaryMap resource.\nFormat should be: <server> <binary name> ...");
  	 return;
        }
***************
*** 93,99 ****
     if(_localRes.use_borg){
     /* find rc */
        rc = findEntry(e->server, _localRes.borgrc_map, &err);
!       if(err == PARSEERROR){
  	 error("Parse error in cyborgXtrekRCMap resource.\nFormat should be <server> <xtrekrc file> ...");
  	 return;
        }
--- 82,88 ----
     if(_localRes.use_borg){
     /* find rc */
        rc = findEntry(e->server, _localRes.borgrc_map, &err);
!       if(err){
  	 error("Parse error in cyborgXtrekRCMap resource.\nFormat should be <server> <xtrekrc file> ...");
  	 return;
        }
***************
*** 106,112 ****
  
     if(!rc){
        rc = findEntry(e->server, _localRes.xtrekrc_map, &err);
!       if(err == PARSEERROR){
  	 error("Parse error in xtrekRCMap resource.\nFormat should be: <server> <xtrekrc file> ...");
  	 return;
        }
--- 95,101 ----
  
     if(!rc){
        rc = findEntry(e->server, _localRes.xtrekrc_map, &err);
!       if(err){
  	 error("Parse error in xtrekRCMap resource.\nFormat should be: <server> <xtrekrc file> ...");
  	 return;
        }
***************
*** 117,130 ****
        }
     }
  
     if(rc)
        sprintf(buf, "exec %s -h %s -p %s -r %s", binary, server, e->port, rc);
     else
        sprintf(buf, "exec %s -h %s -p %s", binary, server, e->port);
     if(_localRes.debug)
        printf("%s\n", buf);
  
!    message("%s -h %s ... ", binary, server);
     
     /* these are allocated by findEntry() */
  
--- 106,134 ----
        }
     }
  
+ #ifdef GATEWAY		/* ATM */
+     {
+        char *cp, *strchr();    /* use index() for BSD */
+        if ((cp = strchr(server, '.')) != NULL) *cp = '\0';
+ 
+        /* assume binary is configured with gateway host/port stuff */
+        if(rc)
+           sprintf(buf, "exec %s -H %s -r %s", binary, server, rc);
+        else
+           sprintf(buf, "exec %s -H %s", binary, server);
+         if (cp != NULL) *cp = '.';
+     }
+ #else
     if(rc)
        sprintf(buf, "exec %s -h %s -p %s -r %s", binary, server, e->port, rc);
     else
        sprintf(buf, "exec %s -h %s -p %s", binary, server, e->port);
+ #endif
+ 
     if(_localRes.debug)
        printf("%s\n", buf);
  
!    message("%s -h %s -p %s ... ", binary, server, e->port);
     
     /* these are allocated by findEntry() */
  
***************
*** 151,203 ****
     message("started.\n");
  }
  
! char *expand(s)
! 
!    char	*s;
! {
!    char	*t;
!    if(*s == '~'){
!       t = strdup(&s[1]);
!       sprintf(s, "%s%s", getenv("HOME"), t);
!       free(t);
!    }
!    return s;
! }
! 
! char *findEntry(name, src, e)
! 
!    char	*name;
!    char	*src;
!    int	*e;
! {
!    register char 	*s = src;
!    int			sv;
!    static 
!    char		buf1[BUFSIZ], buf2[BUFSIZ];
! 
!    *e = NOERROR;
!    if(!s)
!       return NULL;
! 
!    while(*s){
!       sv = sscanf(s, "%s %s", buf1, buf2);
!       if(sv != 2){
! 	 *e = PARSEERROR;
! 	 return NULL;
!       }
!       if(strcmp(buf1, name) == 0)
! 	 return strdup(expand(buf2));
!       
!       while(isspace(*s)) s++;
!       s += strlen(buf1);
!       while(isspace(*s)) s++;
!       s += strlen(buf2);
!       while(isspace(*s)) s++;
!    }
!    return NULL;
! }
! 
! char *getNumeric(name)
  
     char	*name;
  {
--- 155,162 ----
     message("started.\n");
  }
  
! char *
! getNumeric(name)
  
     char	*name;
  {
*** mesg.c	Sun Jul  5 16:25:32 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/mesg.c	Mon Aug  3 18:22:59 1992
***************
*** 13,25 ****
  extern Resources	_localRes;
  extern Globals		_globals;
  
- extern void		message(),
- 			error();
- 
  static char	_message[500];
  static void	_outputMessage();
  
! void error(va_alist)
  
     int	va_alist;
  {
--- 13,24 ----
  extern Resources	_localRes;
  extern Globals		_globals;
  
  static char	_message[500];
+ 
  static void	_outputMessage();
  
! void 
! error(va_alist)
  
     int	va_alist;
  {
***************
*** 27,32 ****
--- 26,33 ----
     char		*format;
     Widget	e = _globals.errorw;
     XmString	mess;
+    int		i;
+    Arg		args[2];
  
     va_start(ap);
     format = va_arg(ap, char *);
***************
*** 38,44 ****
     }
  
     mess = XmStringCreateLtoR(_message, XmSTRING_DEFAULT_CHARSET);
!    XtVaSetValues(e, XmNmessageString, mess, NULL);
     XtManageChild(e);
  
     if(mess)
--- 39,48 ----
     }
  
     mess = XmStringCreateLtoR(_message, XmSTRING_DEFAULT_CHARSET);
!    i=0;
!    XtSetArg(args[i], XmNmessageString, mess);	i++;
!    XtSetValues(e, args, i);
! 
     XtManageChild(e);
  
     if(mess)
***************
*** 49,55 ****
   * Mostly borrowed from Dirk Grunwald's xtex
   */
  
! void message(va_alist)
     
     int	va_alist;
  {
--- 53,60 ----
   * Mostly borrowed from Dirk Grunwald's xtex
   */
  
! void 
! message(va_alist)
     
     int	va_alist;
  {
***************
*** 69,75 ****
     XFlush(XtDisplay(_globals.textw));
  }
  
! static void _outputMessage(w, s)
  
     Widget	w;
     String	s;
--- 74,81 ----
     XFlush(XtDisplay(_globals.textw));
  }
  
! static void 
! _outputMessage(w, s)
  
     Widget	w;
     String	s;
***************
*** 79,85 ****
--- 85,95 ----
     /* find last */
     pos = XmTextGetLastPosition(w);
     XmTextSetInsertionPosition(w, pos);
+ #if XmREVISION == 0
+    XmTextReplace(w, pos, pos, s);
+ #else
     XmTextInsert(w, pos, s);
+ #endif
     /* push the caret to the end of the line */
     XmTextSetInsertionPosition(w, XmTextGetLastPosition(w)-1);
  }
*** metaserver.c	Sun Jul  5 16:25:32 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/metaserver.c	Fri Sep 11 18:46:34 1992
***************
*** 1,8 ****
  #include <stdio.h>
! #include <ctype.h>
! #include <signal.h>
! #include <time.h>
! #include <sys/wait.h>
  
  #include <X11/Intrinsic.h>
  #include <X11/Xos.h>
--- 1,12 ----
  #include <stdio.h>
! #include <sys/types.h>
! #include <sys/time.h>
! #include <sys/socket.h>
! #include <sys/filio.h>
! #include <netinet/in.h>
! #include <arpa/inet.h>
! #include <netdb.h>
! #include <errno.h>
  
  #include <X11/Intrinsic.h>
  #include <X11/Xos.h>
***************
*** 10,26 ****
  
  #include "xnetrekm.h"
  
  /* connect and parse */
  
! extern Resources	_localRes;
! extern Globals		_globals;
  
! extern void		message(),
! 			error();
  
! static char	server_n[MAX_SERVERNAME];
  
! int getServers(l, n)
  
     ServerList	*l;
     int		*n;
--- 14,42 ----
  
  #include "xnetrekm.h"
  
+ #define TIME_LN			32
+ 
+ extern	char			*strptime();
+ 
  /* connect and parse */
  
! extern Resources		_localRes;
! extern Globals			_globals;
  
! static int 			_queryMetaServer();
! static FILE			*_callService();
! static void			_closeService();
! static void			_sortByPreferred();
! static int 			_found();
! static struct tm		*_convertStrToT();
! static char			*_fixTime();
  
! static int 	_sock;
! static char	_server_n[MAX_SERVERNAME];
! static char	_error_s[80];
  
! int 
! getServers(l, n)
  
     ServerList	*l;
     int		*n;
***************
*** 27,54 ****
  {
     register char	*s = _localRes.metaserver_list;
     char         	buf1[MAX_SERVERNAME], buf2[10];
!    int			sv;
  
     /* if this was initialized from a previous call we assume that it
        succeeded. */
!    if(_globals.telnet_com[0] != '\0'){
!       sv = queryMetaServer(l, n);
!       if(sv >= 0)
  	 return sv;
     }
  
     while(*s){
        sv = sscanf(s, "%s %s", buf1, buf2);
!       if(sv != 2){
  	 error("Parse error in metaServerList resource.\nFormat should be <metaserver> <port> ...");
           return -1;
        }
!       sprintf(_globals.telnet_com, "exec telnet %s %s", 
! 	 buf1, buf2);
!       strcpy(_globals.metaserver, buf1);	/* xx */
!       sv = queryMetaServer(l, n);
!       if(sv >= 0)
! 	 return sv;
        
        while(isspace(*s)) s++;
        s += strlen(buf1);
--- 43,83 ----
  {
     register char	*s = _localRes.metaserver_list;
     char         	buf1[MAX_SERVERNAME], buf2[10];
!    int			sv, port;
!    char			*ptr;
  
     /* if this was initialized from a previous call we assume that it
        succeeded. */
!    if(_globals.metaserver[0] != '\0'){
!       sv = _queryMetaServer(l, n);
!       if(sv >= 0){
! 	 if(_localRes.preferred_serverlist)
! 	    _sortByPreferred(l, *n);
  	 return sv;
+       }
     }
  
     while(*s){
        sv = sscanf(s, "%s %s", buf1, buf2);
!       port = atoi(buf2);
!       if(sv != 2 || (port == 0 /* xx */)){
! 	 *n = 0;
  	 error("Parse error in metaServerList resource.\nFormat should be <metaserver> <port> ...");
           return -1;
        }
! 
!       /* meaning that we tried this already at the top */
!       if(strcmp(_globals.metaserver, buf1) != 0){
! 	 strcpy(_globals.metaserver, buf1);
! 	 _globals.metaserver_port = port;
! 
! 	 sv = _queryMetaServer(l, n);
! 	 if(sv >= 0){
! 	    if(_localRes.preferred_serverlist)
! 	       _sortByPreferred(l, *n);
! 	    return sv;
! 	 }
!       }
        
        while(isspace(*s)) s++;
        s += strlen(buf1);
***************
*** 57,132 ****
        while(isspace(*s)) s++;
     }
  
!    _globals.telnet_com[0] = '\0';
     return -1;
  }
  
! static int	_killed;
  
- int queryMetaServer(l, n)
- 
     ServerList	*l;
     int		*n;
  {
!    FILE			*mi, *my_popen();
     static char		buf[256];
!    static char		time[10];
!    int			port, players, sv, index = 0, wq, killtelnet();
!    struct itimerval	udt;
  
     *n = 0;
-    _killed = 0;
     XFlush(_globals.display);
  
     if(_globals.textw)
        message("Calling metaserver at %s ... ", _globals.metaserver);
     
!    /* start a timer so we won't hang indefinitely */
!    signal(SIGALRM, killtelnet);
!    udt.it_interval.tv_sec = _localRes.metaserver_timeout;
!    udt.it_interval.tv_usec = 0;
!    udt.it_value.tv_sec = _localRes.metaserver_timeout;
!    udt.it_value.tv_usec = 0;
!    (void) setitimer(ITIMER_REAL, &udt, (struct itimerval *) 0);
  
-    mi = my_popen(_globals.telnet_com, "r");
-    if(_localRes.debug)
-       printf("%s\n", _globals.telnet_com);
     if(!mi) {
        if(_globals.textw)
! 	 message("Metaserver \"%s\" session failed.\n", _globals.metaserver);
        else
  	 fprintf(stderr, "Metaserver \"%s\" failed\n", _globals.metaserver);
-       itimoff();
        return -1; 
     }
     buf[0] = '\0';
     while(fgets(buf, 254, mi)){
  
-       /* try to catch telnet errors */
-       if(strstr(buf, "unknown host")){
- 	 if(_globals.textw)
- 	    message("Unknown host \"%s\".\n", _globals.metaserver);
- 	 else
- 	    fprintf(stderr, "%s: Unknown host \"%s\".", 
- 	       _globals.program, _globals.metaserver);
- 	 _killtelnet();
- 	 pclose(mi);
- 	 return -1;
-       }
- 
        wq = -1;
        players = -1;
!       server_n[0] = '\0';
!       time[0] = '\0';
  
        /* try to match several formats */
!       sv = sscanf(buf, "%[^(](%d) : %d Players online at %s", server_n, 
! 	 &port, &players, time);
  
        if(sv != 4){
! 	 sv = sscanf(buf, "%[^(](%d) : Wait Queue %d at %s",
! 	    server_n, &port, &wq, time);
  	 if(sv != 4)
  	    continue;	/* assume server error message (Can't connect..) */
        }
--- 86,163 ----
        while(isspace(*s)) s++;
     }
  
!    _globals.metaserver[0] = '\0';
!    *n = 0;
     return -1;
  }
  
! static int 
! _queryMetaServer(l, n)
  
     ServerList	*l;
     int		*n;
  {
!    FILE			*mi;
     static char		buf[256];
!    static char		time_s[TIME_LN];
!    int			port, players, sv, index = 0, wq;
!    struct servent	*daytime_service;
!    struct tm		*timev = NULL;
  
     *n = 0;
     XFlush(_globals.display);
  
+ #ifdef nodef
+    if(_localRes.use_timeserver){
+       daytime_service = getservbyname("daytime", "tcp");
+       if(daytime_service){
+ 	 mi = _callService(_globals.metaserver, daytime_service->s_port);
+ 	 if(!mi){
+ 	    message("Daytime service from %s not available.\n");
+ 	 }
+ 	 else{
+ 	    timev = _convertStrToT(fgets(buf, 254, mi));
+ 	    _closeService(mi);
+ 	 }
+       }
+       else {
+ 	 message("Daytime service not available\n");
+       }
+    }
+ #endif
+ 
     if(_globals.textw)
        message("Calling metaserver at %s ... ", _globals.metaserver);
     
!    mi = _callService(_globals.metaserver, _globals.metaserver_port);
  
     if(!mi) {
        if(_globals.textw)
! 	 message("\nMetaserver \"%s\" session failed (%s).\n", 
! 	    _globals.metaserver, _error_s);
        else
  	 fprintf(stderr, "Metaserver \"%s\" failed\n", _globals.metaserver);
        return -1; 
     }
+    _globals.last_refresh = time(NULL);
+ 
     buf[0] = '\0';
     while(fgets(buf, 254, mi)){
  
        wq = -1;
        players = -1;
!       _server_n[0] = '\0';
!       time_s[0] = '\0';
  
+       if(_localRes.debug)
+ 	 printf("%s", buf);
        /* try to match several formats */
!       sv = sscanf(buf, "%[^(](%d) : %d Players online at %s", _server_n, 
! 	 &port, &players, time_s);
  
        if(sv != 4){
! 	 sv = sscanf(buf, "%[^(](%d) : Wait %*[Qq]ueue %d at %s",
! 	    _server_n, &port, &wq, time_s);
  	 if(sv != 4)
  	    continue;	/* assume server error message (Can't connect..) */
        }
***************
*** 142,159 ****
        else
  	 continue;
  
!       sprintf(l[index].server, "%s", server_n);
        sprintf(l[index].port, "%d", port);
!       sprintf(l[index].time, "%s", time);
        index ++;
     }
!    my_pclose(mi);
!    itimoff();
     *n = index;
  
-    if(_killed)
-       return -1;
- 
     if(_globals.textw)
        message("done.\n");
  
--- 173,187 ----
        else
  	 continue;
  
!       sprintf(l[index].server, "%s", _server_n);
        sprintf(l[index].port, "%d", port);
!       sprintf(l[index].time, "%s", _fixTime(time_s, timev));
        index ++;
     }
!    _closeService(mi);
! 
     *n = index;
  
     if(_globals.textw)
        message("done.\n");
  
***************
*** 160,202 ****
     return 0;
  }
  
- killtelnet()
- {
-    if(_globals.textw)
-       message("Metaserver \"%s\" timed out.\n", _globals.metaserver);
-    else
-       fprintf(stderr, "Metaserver \"%s\" timed out.\n", _globals.metaserver);
-    _killtelnet();
- }
- 
- _killtelnet()
- {
-    extern int 	popen_pid;		/* my_popen.c */
-    /*
-    int		pid;
-    pid = getpgrp(popen_pid);
-    */
- 
-    _killed = 1;
- 
-    (void) kill(popen_pid, SIGKILL);
- }
- 
- itimoff()
- {
-    struct itimerval	udt;
- 
-    signal(SIGALRM, SIG_IGN);
-    udt.it_interval.tv_sec = 0;
-    udt.it_interval.tv_usec = 0;
-    udt.it_value.tv_sec = 0;
-    udt.it_value.tv_usec = 0;
-    setitimer(ITIMER_REAL, &udt, 0);
- }
- 
  /* parse resource, not server list */
  
! int getResourceServerList(l, n)
  
     ServerList	*l;
     int		*n;
--- 188,197 ----
     return 0;
  }
  
  /* parse resource, not server list */
  
! int 
! getResourceServerList(l, n)
  
     ServerList	*l;
     int		*n;
***************
*** 212,223 ****
  
     /* read list of form <server> <port> <server> <port> etc.. */
     while(*s){
!       sv = sscanf(s, "%s %s", server_n, port);
        if(sv != 2){
  	 error("Parse error in serverList resource.\nFormat should be: <host> <port> ...");
  	 return -1;
        }
!       strcpy(l[index].server, server_n);
        strcpy(l[index].port, port);
        l[index].status = FRESOURCE;
        l[index].players[0] = '\0';
--- 207,218 ----
  
     /* read list of form <server> <port> <server> <port> etc.. */
     while(*s){
!       sv = sscanf(s, "%s %s", _server_n, port);
        if(sv != 2){
  	 error("Parse error in serverList resource.\nFormat should be: <host> <port> ...");
  	 return -1;
        }
!       strcpy(l[index].server, _server_n);
        strcpy(l[index].port, port);
        l[index].status = FRESOURCE;
        l[index].players[0] = '\0';
***************
*** 225,231 ****
        index ++;
  
        while(isspace(*s)) s++;
!       s += strlen(server_n);
        while(isspace(*s)) s++;
        s += strlen(port);
        while(isspace(*s)) s++;
--- 220,226 ----
        index ++;
  
        while(isspace(*s)) s++;
!       s += strlen(_server_n);
        while(isspace(*s)) s++;
        s += strlen(port);
        while(isspace(*s)) s++;
***************
*** 233,236 ****
--- 228,449 ----
     *n = index;
  
     return 0;
+ }
+ 
+ static FILE *
+ _callService(host, port)
+ 
+    char	*host;
+    int	port;
+ {
+    struct sockaddr_in	addr;
+    struct hostent	*hp;
+    struct timeval	timeout;
+    fd_set		writefds;
+    int			count = 0;
+    int			sv = -1;
+    int			non_block;
+ 
+    if(_localRes.debug){
+       printf("calling %s at port %d\n",
+ 	 host, port);
+    }
+ 
+    /* stripped from Andy McFadden's trekhopd */
+ 
+    if((_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
+       perror("metaserver socket");
+       sprintf(_error_s, "socket creation failed");
+       return NULL;
+    }
+ 
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    if ((addr.sin_addr.s_addr = inet_addr(host)) == -1){
+       if ((hp = gethostbyname(host)) == NULL){
+ 	 fprintf(stderr, "%s: unknown host\n", host);
+ 	 close(_sock);
+ 	 sprintf(_error_s, "unknown host");
+ 	 return NULL;
+       }
+       else
+ 	 addr.sin_addr.s_addr = *(long *) hp->h_addr;
+    }
+ 
+    non_block = 1;
+    ioctl(_sock, FIONBIO, &non_block);
+ 
+    /* by selecting the socket for write we can determine if the
+       connect call will complete before hand */
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+    FD_ZERO(&writefds);
+    FD_SET(_sock, &writefds);
+ 
+    while(1){
+       if(connect(_sock, &addr, sizeof(addr)) == 0){
+ 	 /* connection completed */
+ 	 break;
+       }
+       /* might connect between select below and here */
+       else if(errno == EISCONN)
+ 	 break;
+       
+       /*
+       printf("connect failed; %d\n", errno);
+       */
+       
+       switch(errno){
+ 	 /* these errors are ok */
+ 	 case EINPROGRESS:
+ 	 case EALREADY:
+ 	    while(XtAppPending(_globals.app_context)){
+ 	       XtAppProcessEvent(_globals.app_context, XtIMAll);
+ 	    }
+ 	    count ++;
+ 	    if(count == _localRes.metaserver_timeout+1){
+ 	       /* timeout */
+ 	       close(_sock);
+ 	       sprintf(_error_s, "connection timed out");
+ 	       return NULL;
+ 	    }
+ 	    break;
+ 	 
+ 	 default:
+ 	    /* connect error */
+ 	    perror("connect");
+ 	    close(_sock);
+ 	    sprintf(_error_s, "connect failure");
+ 	    return NULL;
+       }
+       sv = select(32, NULL, &writefds, NULL, &timeout);
+ #ifdef nodef
+       if(sv == 1)
+ 	 break;		/* connection succeeded */
+ #endif
+    }
+ 
+    non_block = 0;
+    ioctl(_sock, FIONBIO, &non_block);
+ 
+    return fdopen(_sock, "r");
+ }
+ 
+ static void 
+ _closeService(f)
+    
+    FILE	*f;
+ {
+    fclose(f);
+    shutdown(_sock);
+ }
+ 
+ static void 
+ _sortByPreferred(l, n)
+ 
+    ServerList	*l;
+    int		n;
+ {
+    register	i, j, fnd_i;
+    char		**psl = _globals.preferred_serverlist;
+    int		n_psl = _globals.num_preferred, l_ind;
+    ServerList	**fnd = (ServerList **) malloc(sizeof(ServerList *) * n_psl),
+ 		*new = (ServerList *) malloc(sizeof(ServerList) * n);
+ 
+    for(i=0,fnd_i=0; i< n_psl; i++){
+       if(_found(psl[i], l, n, &l_ind)){
+ 	 fnd[fnd_i++] = &l[l_ind];
+       }
+    }
+    for(i=0; i< fnd_i; i++){
+       bcopy(fnd[i], &new[i], sizeof(ServerList));
+       /* mark as copied */
+       fnd[i]->status = 0;
+    }
+    j = i;
+    for(i=0; i< n; i++){
+       if(l[i].status)
+ 	 bcopy(&l[i], &new[j++], sizeof(ServerList));
+    }
+    bcopy(new, l, sizeof(ServerList) * n);
+ 
+    free((char *) fnd);
+    free((char *) new);
+ }
+ 
+ static int
+ _found(ps, l, n, index)
+ 
+    char		*ps;
+    ServerList	*l;
+    int		n;
+    int		*index;
+ {
+    register	i;
+    for(i=0; i< n; i++){
+       if(strcmp(ps, l[i].server) == 0){
+ 	 *index = i;
+ 	 return 1;
+       }
+    }
+    return 0;
+ }
+ 
+ /* convert time string from daytime service to time_t */
+ 
+ static struct tm
+ *_convertStrToT(s)
+ 
+    char	*s;
+ {
+    static
+    struct tm	timeval;
+    char	*r;
+ 
+    if((r=strptime(s, "%a %h %e %T %Z %Y", &timeval)) != s+1){
+       fprintf(stderr, "_convertStrToT: strptime failed at character %d in '%s'\n",
+ 	 s-r, s);
+       return NULL;
+    }
+    return &timeval;
+ }
+ 
+ /* convert time string s to our time.  s changed in place and returned */
+ 
+ static char *
+ _fixTime(s, ms_time)
+ 
+    char		*s;
+    struct tm	*ms_time;	/* time value from time service */
+ {
+    struct tm	f_time, his_time, *our_time;
+    time_t	tsecs;
+    char		ntime[TIME_LN], *r;
+ 
+    if(!ms_time) 	/* service not needed or failed */
+       return s;
+    
+    
+    if((r=strptime(s, "%T", &f_time)) != s+1){
+       fprintf(stderr, "_fixTime: strptime failed at character %d in '%s'\n",
+ 	 s-r, s);
+       return s;
+    }
+    bcopy(ms_time, &his_time, sizeof(struct tm));
+    his_time.tm_hour 	= f_time.tm_hour;
+    his_time.tm_min 	= f_time.tm_min;
+    his_time.tm_sec 	= f_time.tm_sec;
+ 
+    /* now new_time contains the full time entry for this server time field
+       in their time zone */
+    
+    tsecs = timelocal(&his_time);
+    our_time = localtime(&tsecs);
+ 
+    if(strftime(ntime, TIME_LN, "%I:%M %p", &our_time) == 0){
+       fprintf(stderr, "strftime failed\n");
+       return s;
+    }
+    strcpy(s, ntime);
+    return s;
  }
*** patchlevel.h	Wed Apr 14 11:59:20 1993
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/patchlevel.h	Wed Apr 14 12:02:20 1993
***************
*** 0 ****
--- 1,2 ----
+ /* store patchlevel info here for official updates */
+ #define PATCHLEVEL 1
*** popen.c	Sun Jul  5 16:25:32 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/popen.c	Sat Aug  1 08:27:52 1992
***************
*** 12,18 ****
  
  int popen_pid;
  
! FILE *my_popen(cmd, mode)
     
     char	*cmd;
     char	*mode;
--- 12,19 ----
  
  int popen_pid;
  
! FILE *
! myPopen(cmd, mode)
     
     char	*cmd;
     char	*mode;
***************
*** 46,52 ****
     return fdopen(myside, mode);
  }
  
! int my_pclose(ptr)
     
     FILE	*ptr;
  {
--- 47,54 ----
     return fdopen(myside, mode);
  }
  
! int 
! myPclose(ptr)
     
     FILE	*ptr;
  {
***************
*** 70,84 ****
     signal(SIGQUIT, SIG_DFL);
     signal(SIGHUP, SIG_DFL);
     return status;
- }
- 
- detach()
- {
-    int fd;
- 
-    fd = open("/dev/tty", O_RDWR, 0);
-    if (fd < 0)
-       return;
-    (void) ioctl(fd, TIOCNOTTY, (char *) NULL);
-    (void) close(fd);
  }
--- 72,75 ----
*** str.c	Sun Jul  5 16:25:33 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/str.c	Sat Aug  1 08:34:46 1992
***************
*** 1,6 ****
  #include <stdio.h>
  
! char *strdup(s)
     char *s;
  {
     char *n;
--- 1,7 ----
  #include <stdio.h>
  
! char *
! strdup(s)
     char *s;
  {
     char *n;
***************
*** 12,18 ****
     return n;
  }
  
! char *strstr(x, y)
  
     char *x, *y;
  {
--- 13,20 ----
     return n;
  }
  
! char *
! strstr(x, y)
  
     char *x, *y;
  {
*** strutil.c	Wed Apr 14 11:58:46 1993
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/strutil.c	Sat Aug  1 16:55:16 1992
***************
*** 0 ****
--- 1,118 ----
+ #include <stdio.h>
+ #include <ctype.h>
+ 
+ extern char		*strdup();
+ 
+ char			*homeExpand();
+ 
+ char *
+ findEntry(name, src, e)
+ 
+    char	*name;
+    char	*src;
+    int	*e;
+ {
+    register char 	*s = src;
+    int			sv;
+    static 
+    char		buf1[BUFSIZ], buf2[BUFSIZ];
+ 
+    *e = 0;
+    if(!s)
+       return NULL;
+ 
+    while(*s){
+       sv = sscanf(s, "%s %s", buf1, buf2);
+       if(sv != 2){
+ 	 *e = 1;
+ 	 return NULL;
+       }
+       if(strcmp(buf1, name) == 0)
+ 	 return strdup(homeExpand(buf2));
+       
+       while(isspace(*s)) s++;
+       s += strlen(buf1);
+       while(isspace(*s)) s++;
+       s += strlen(buf2);
+       while(isspace(*s)) s++;
+    }
+    return NULL;
+ }
+ 
+ char **
+ getPreferredServerList(l, n, e)
+ 
+    char	*l;
+    int	*n;		/* num found */
+    int	*e;		/* error */
+ {
+    register char	*s = l;
+    register		i, index;
+    int			sv;
+    char			buf1[64], **new;
+ 
+    *n = 0;
+    *e = 0;
+ 
+    index = 0;
+ 
+    while(*s){
+       while(isspace(*s)) s++;
+       if(*s){
+ 	 while(!isspace(*s) && *s) s++;
+ 	 index ++;
+       }
+    }
+    if(!index){
+       *e = 1;
+       return NULL;
+    }
+    *n = index;
+    s = l;
+ 
+    new = (char **) malloc(sizeof(char *) * index);
+    index = 0;
+    while(*s){
+       while(isspace(*s)) s++;
+       i=0;
+       while(!isspace(*s) && *s){
+ 	 buf1[i++] = *s;
+ 	 s++;
+       }
+       buf1[i] = '\0';
+       new[index] = strdup(buf1);
+       index++;
+    }
+ 
+    return new;
+ }
+ 
+ char *homeExpand(s)
+ 
+    char *s;
+ {
+    char *t;
+    if(*s == '~'){
+       t = strdup(&s[1]);
+       sprintf(s, "%s%s", getenv("HOME"), t);
+       free(t);
+    }
+    return s;
+ }
+ 
+ char *baseName(s)
+ 
+    char	*s;
+ {
+    static
+    char		buf[64];
+    char		*t;
+    extern char	*rindex();
+ 
+    if((t=rindex(s, '/'))){
+       strcpy(buf, t+1);
+    }
+    else
+       strcpy(buf, s);
+    return buf;
+ }
No differences encountered
*** xnetrekm.c	Mon Jul  6 13:20:38 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/xnetrekm.c	Wed Apr 14 12:18:20 1993
***************
*** 2,8 ****
  static char rcsid[] = "XNetrekM  $Revision: 1.0 $ ($Date: 1992/07/06 05:29:27 $)";
  
  #include <stdio.h>
- #include <time.h>
  #include <sys/types.h>
  #include <sys/wait.h>
  #include <signal.h>
--- 2,7 ----
***************
*** 11,24 ****
  #include <X11/Xos.h>
  #include <X11/StringDefs.h>
  
  #define CS			"ISOLatin1"
  #define QUIT			"QUIT"
  #define INITIAL_SERVER_ENTRIES	25		/* cache entry widgets so we
  						   don't have to create them
  						   later */
- #define ENTRY_WIDGETS		5		/* # widgets for each entry that
- 						   have the form as parent */
- 
  #include <Xm/Xm.h>
  #include <Xm/CascadeB.h>
  #include <Xm/Form.h>
--- 10,24 ----
  #include <X11/Xos.h>
  #include <X11/StringDefs.h>
  
+ /* showing the port seems to be a waste of space.. */
+ /*
+ #define SHOWPORT
+ */
  #define CS			"ISOLatin1"
  #define QUIT			"QUIT"
  #define INITIAL_SERVER_ENTRIES	25		/* cache entry widgets so we
  						   don't have to create them
  						   later */
  #include <Xm/Xm.h>
  #include <Xm/CascadeB.h>
  #include <Xm/Form.h>
***************
*** 34,55 ****
  #include <Xm/ToggleB.h>
  #include "xnetrekm.h"
  
  Resources 		_localRes;
  Globals			_globals;
  
- extern void		message(),
- 			error();
- 
  static Boolean	false	= False;
  static Boolean	true	= True;
  
- 
  typedef struct {
     Widget	serverW,
  		portW,	portF,
  		playersW, playersF,
  		timeW, timeF,
! 		pingW;
     Boolean	realized;
     Boolean	managed;
  } ServerWList;
--- 34,58 ----
  #include <Xm/ToggleB.h>
  #include "xnetrekm.h"
  
+ #include "patchlevel.h"
+ 
+ #if XmREVISION == 0
+ #define NO_MW			/* no message window in XmMainWindow */
+ #endif
+ 
  Resources 		_localRes;
  Globals			_globals;
  
  static Boolean	false	= False;
  static Boolean	true	= True;
  
  typedef struct {
     Widget	serverW,
  		portW,	portF,
  		playersW, playersF,
  		timeW, timeF,
! 		pingW,
! 		altPW;
     Boolean	realized;
     Boolean	managed;
  } ServerWList;
***************
*** 58,64 ****
  static ServerWList	_serverWList[MAX_SERVERS];
  static int		_numServers;
  
! static Widget		_workarea,
  			_title, 
  			_helpw,
  			_refresh,
--- 61,67 ----
  static ServerWList	_serverWList[MAX_SERVERS];
  static int		_numServers;
  
! static Widget		_server_workarea,
  			_title, 
  			_helpw,
  			_refresh,
***************
*** 67,73 ****
  			_toggle_resource;
  
  static String fallback_resources [] = {
!    "XNetrekM.geometry:			580x462",
     "XNetrekM.serverList:		calvin.usc.edu 2592 \
  					bronco.ece.cmu.edu 2592",
     "XNetrekM*resizable:			False",
--- 70,80 ----
  			_toggle_resource;
  
  static String fallback_resources [] = {
!    "XNetrekM.geometry:			580x482",
!    "XNetrekM.baseHeight:		1",
!    "XNetrekM.baseWidth:			1",
!    "XNetrekM.minHeight:			320",
!    "XNetrekM.minWidth:			550",
     "XNetrekM.serverList:		calvin.usc.edu 2592 \
  					bronco.ece.cmu.edu 2592",
     "XNetrekM*resizable:			False",
***************
*** 89,102 ****
     "XNetrekM*time_title.width:		60",
     "XNetrekM*time_title.marginHeight:	6",
     "XNetrekM*time_title.leftOffset:	2",
!    "XNetrekM*ping.leftOffset:		4",
  
  /* fonts */
  
!    "XNetrekM*fontList:			variable",
     "XNetrekM*port*fontList:		-adobe-helvetica-medium-r-normal--12-*",
     "XNetrekM*time*fontList:		-adobe-helvetica-medium-r-normal--12-*",
     "XNetrekM*text*fontList:		-adobe-helvetica-medium-r-normal--12-*",
  
  /* colors */
     "XNetrekM*foreground:                 		black",
--- 96,114 ----
     "XNetrekM*time_title.width:		60",
     "XNetrekM*time_title.marginHeight:	6",
     "XNetrekM*time_title.leftOffset:	2",
!    "XNetrekM*ping.leftOffset:		6",
!    "XNetrekM*text.rows:			4",
!    "XNetrekM*textSW.height:		132",	/* kludge */
  
  /* fonts */
  
!    "XNetrekM*fontList:			-adobe-helvetica-bold-r-normal--12-*",
     "XNetrekM*port*fontList:		-adobe-helvetica-medium-r-normal--12-*",
     "XNetrekM*time*fontList:		-adobe-helvetica-medium-r-normal--12-*",
+    /*
     "XNetrekM*text*fontList:		-adobe-helvetica-medium-r-normal--12-*",
+    */
+    "XNetrekM*text*fontList:		-misc-fixed-medium-r-normal--13-*",
  
  /* colors */
     "XNetrekM*foreground:                 		black",
***************
*** 107,112 ****
--- 119,125 ----
     "XNetrekM*refresh.background:         		LightSteelBlue4",
     "XNetrekM*quit.foreground:            		red3",
     "XNetrekM*ping.foreground:            		blue3",
+    "XNetrekM*alt.foreground:            		black",
     "XNetrekM*text.foreground:            		white",
     "XNetrekM*textSW*background:          		LightSteelBlue4",
  
***************
*** 144,151 ****
--- 157,176 ----
      XtOffset(Resources *, use_borg), XtRBoolean, (XtPointer)&false},
    { "serverAddressMap", "ServerAddressMap", XtRString, sizeof(String),
      XtOffset(Resources *, serveraddress_map), XtRString, NULL},
+   { "preferredServerList", "PreferredServerList", XtRString, sizeof(String),
+     XtOffset(Resources *, preferred_serverlist), XtRString, NULL},
    { "debug", "Debug", XtRBoolean, sizeof(Boolean),
      XtOffset(Resources *, debug), XtRBoolean, (XtPointer)&false},
+   /* OBSOLETE */
+   { "altProgram", "AltProgram", XtRString, sizeof(String),
+     XtOffset(Resources *, alt_program), XtRString, NULL},
+   /* OBSOLETE */
+   { "useTimeServer", "UseTimeServer", XtRBoolean, sizeof(Boolean),
+      XtOffset(Resources *, use_timeserver), XtRBoolean, (XtPointer)&true},
+   { "refreshOnDeiconify", "RefreshOnDeiconify", XtRBoolean, sizeof(Boolean),
+      XtOffset(Resources *,refresh_on_deiconify),XtRBoolean,(XtPointer)&true},
+   { "minAutoRefresh", "MinAutoRefresh", XtRInt, sizeof(int),
+     XtOffset(Resources *, min_autorefresh), XtRString, (XtPointer) "15"},
  };
  
  static XrmOptionDescRec options[] = {
***************
*** 154,185 ****
     {"-debug",	".debug",		XrmoptionNoArg, "TRUE"},
  };
  
! Widget	createHelp();
! void 	createServerButtons();
! int 	updateServerButtons();
! Widget 	createEntry();
! void 	changeLabels();
  
! static void helpCB();
! static void callCB();
! static void exitCB();
! static void updateCB();
! static void usemetaCB();
! static void showCB();
! static void pingCB();
! static void borgCB();
  
! static void usage();
  
! int reaper();
  
! void main(argc, argv)
  
     int	argc;
     char	**argv;
  {
     XtAppContext	app_context;
     Widget	app_shell,
  		mainw,
  		menu_bar,
  		menu,
--- 179,218 ----
     {"-debug",	".debug",		XrmoptionNoArg, "TRUE"},
  };
  
! static Widget		_createHelp();
! static void 		_createServerButtons();
! static int 		_updateServerButtons();
! static Widget 		_createEntry();
! static void 		_changeLabels();
  
! static void 		_helpCB();
! static void 		_callCB();
! static void 		_exitCB();
! static void 		_updateCB();
! static void 		_usemetaCB();
! static void 		_showCB();
! static void 		_pingCB();
! static void 		_altCB();
! static void 		_borgCB();
  
! static XtEventHandler	_refreshOnDeiconify();
  
! static void 		_usage();
  
! static void 		_reaper();
! static void 		_boundCheck();
  
+ void 
+ main(argc, argv)
+ 
     int	argc;
     char	**argv;
  {
     XtAppContext	app_context;
     Widget	app_shell,
+ #ifdef NO_MW
+ 		top_form,
+ #endif
  		mainw,
  		menu_bar,
  		menu,
***************
*** 194,217 ****
  		rc;
     register	i;
     Arg		args[16];
  
!    app_shell = XtVaAppInitialize(&app_context, "XNetrekM", options,
!       XtNumber(options), &argc, argv, fallback_resources, NULL);
     XtGetApplicationResources(app_shell, (caddr_t)&_localRes,
        resources, XtNumber(resources), NULL, 0);
  
     _globals.program = argv[0];
  
     if(argc > 1)
!       usage(_globals.program, argv+1);
  
!    (void) signal(SIGCHLD, reaper);
     /* ignore these signals caused by children */
     (void) signal(SIGTTOU, SIG_IGN);
     (void) signal(SIGTTIN, SIG_IGN);
  
     _globals.display = XtDisplay(app_shell);
!    _globals.telnet_com[0] = '\0';
  
     /* set up widgets. */
  
--- 227,259 ----
  		rc;
     register	i;
     Arg		args[16];
+    int		n;
+    XmString	aval1, aval2;
  
!    app_shell = XtAppInitialize(&app_context,  "XNetrekM", options,
!       XtNumber(options), &argc, argv, fallback_resources, NULL, 0);
!    _globals.app_context = app_context;
     XtGetApplicationResources(app_shell, (caddr_t)&_localRes,
        resources, XtNumber(resources), NULL, 0);
  
     _globals.program = argv[0];
  
+    XtAddEventHandler(app_shell, StructureNotifyMask, False,
+       _refreshOnDeiconify, (Opaque) NULL);
+ 
     if(argc > 1)
!       _usage(_globals.program, argv+1);
  
!    (void) signal(SIGCHLD, _reaper);
! #ifndef SYSV
     /* ignore these signals caused by children */
     (void) signal(SIGTTOU, SIG_IGN);
     (void) signal(SIGTTIN, SIG_IGN);
+ #endif
  
     _globals.display = XtDisplay(app_shell);
!    _globals.metaserver[0] = '\0';
!    _globals.last_refresh = 0;
  
     /* set up widgets. */
  
***************
*** 226,235 ****
  
     _globals.errorw = errorw;
  
     i=0;
     XtSetArg(args[i], XmNshowSeparator, True);		i++;
     XtSetArg(args[i], XmNscrollingPolicy, XmAUTOMATIC);	i++;
!    mainw = XmCreateMainWindow(app_shell, "main", args, i);
  
     /* menu bar */
     i=0;
--- 268,293 ----
  
     _globals.errorw = errorw;
  
+ #ifdef NO_MW
     i=0;
+    top_form = XmCreateForm(app_shell, "top_form", args, i);
+ #endif
+ 
+    i=0;
+ #ifdef NO_MW
+    XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM);	i++;
+    XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM);	i++;
+    XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM);i++;
+ #endif
     XtSetArg(args[i], XmNshowSeparator, True);		i++;
     XtSetArg(args[i], XmNscrollingPolicy, XmAUTOMATIC);	i++;
!    mainw = XmCreateMainWindow(
! #ifdef NO_MW
! 				top_form,
! #else
! 				app_shell, 
! #endif
! 						"main", args, i);
  
     /* menu bar */
     i=0;
***************
*** 248,266 ****
     /* buttons */
     i=0;
     XtSetArg(args[i], XmNaccelerator, "Ctrl<Key>Q");	i++;
!    XtSetArg(args[i], XmNacceleratorText, XmStringCreateSimple("^Q")); i++;
!    XtSetArg(args[i], XmNlabelString, XmStringCreateSimple("Quit")); i++;
     button = XmCreatePushButton(menu, "quit", args, i);
!    XtAddCallback(button, XmNactivateCallback, exitCB, 0);
     XtManageChild(button);
  
     /* help message popup */
!    _helpw = createHelp(menu_bar);
  
     /* help button on right of menu bar */
     i=0;
     cascade = XmCreateCascadeButton(menu_bar, "Help", args, i);
!    XtAddCallback(cascade, XmNactivateCallback, helpCB, 0);
     XtManageChild(cascade);
  
     /* tell menu_bar which is help button */
--- 306,329 ----
     /* buttons */
     i=0;
     XtSetArg(args[i], XmNaccelerator, "Ctrl<Key>Q");	i++;
!    aval1 = XmStringCreateLtoR("^Q", XmSTRING_DEFAULT_CHARSET);
!    XtSetArg(args[i], XmNacceleratorText, aval1); i++;
!    aval2 = XmStringCreateLtoR("Quit", XmSTRING_DEFAULT_CHARSET);
!    XtSetArg(args[i], XmNlabelString, aval2); i++;
     button = XmCreatePushButton(menu, "quit", args, i);
!    XtAddCallback(button, XmNactivateCallback, _exitCB, 0);
     XtManageChild(button);
  
+    XmStringFree(aval1);
+    XmStringFree(aval2);
+ 
     /* help message popup */
!    _helpw = _createHelp(menu_bar);
  
     /* help button on right of menu bar */
     i=0;
     cascade = XmCreateCascadeButton(menu_bar, "Help", args, i);
!    XtAddCallback(cascade, XmNactivateCallback, _helpCB, 0);
     XtManageChild(cascade);
  
     /* tell menu_bar which is help button */
***************
*** 268,294 ****
     XtSetArg(args[0], XmNmenuHelpWidget, cascade);	i++;
     XtSetValues(menu_bar, args, i);
  
!    XtManageChild(menu_bar);
  
     i=0;
!    _workarea = XmCreateForm(mainw, "work_area", args, i);
     /* fill work area with server info */
-    createServerButtons(_workarea);
  
!    XtManageChild(_workarea);
  
     /* command window */
     i=0;
     XtSetArg(args[i], XmNorientation, XmHORIZONTAL);	i++;
     commandw = XmCreateRowColumn(mainw, "command", args, i);
-    XtManageChild(commandw);
  
     /* refresh */
     i=0;
!    XtSetArg(args[i], XmNlabelString, XmStringCreateSimple(" Refresh ")); i++;
     _refresh = XmCreatePushButton(commandw, "refresh", args, i);
!    XtAddCallback(_refresh, XmNactivateCallback, updateCB, 0);
     XtManageChild(_refresh);
  
     if(_localRes.use_serverlist)
        XtSetSensitive(_refresh, False);
--- 331,371 ----
     XtSetArg(args[0], XmNmenuHelpWidget, cascade);	i++;
     XtSetValues(menu_bar, args, i);
  
!    if(_localRes.preferred_serverlist){
!       int	e;
!       /* strutil.c */
!       _globals.preferred_serverlist = 
! 	 getPreferredServerList(_localRes.preferred_serverlist, &n, &e);
!       _globals.num_preferred = n;
!       if(e){
! 	 fprintf(stderr, "%s: parse erorr in preferredServerList resource.\n",
! 	    _globals.program);
! 	 fprintf(stderr, "Format should be <server> <server> ...\n");
! 	 _localRes.preferred_serverlist = NULL;
!       }
!    }
  
     i=0;
!    _server_workarea = XmCreateForm(mainw, "work_area", args, i);
     /* fill work area with server info */
  
!    _globals.entry_widgets = 0;
  
+    _createServerButtons(_server_workarea);
+ 
     /* command window */
     i=0;
     XtSetArg(args[i], XmNorientation, XmHORIZONTAL);	i++;
     commandw = XmCreateRowColumn(mainw, "command", args, i);
  
     /* refresh */
     i=0;
!    aval1 = XmStringCreateLtoR(" Refresh ", XmSTRING_DEFAULT_CHARSET);
!    XtSetArg(args[i], XmNlabelString, aval1); i++;
     _refresh = XmCreatePushButton(commandw, "refresh", args, i);
!    XtAddCallback(_refresh, XmNactivateCallback, _updateCB, 0);
     XtManageChild(_refresh);
+    XmStringFree(aval1);
  
     if(_localRes.use_serverlist)
        XtSetSensitive(_refresh, False);
***************
*** 308,314 ****
        XtSetArg(args[i], XmNset, True);		i++;
     }
     toggle = XmCreateToggleButtonGadget(rc, "Use metaserver", args, i);
!    XtAddCallback(toggle, XmNvalueChangedCallback, usemetaCB, True);
     XtManageChild(toggle);
     _toggle_meta = toggle;
  
--- 385,391 ----
        XtSetArg(args[i], XmNset, True);		i++;
     }
     toggle = XmCreateToggleButtonGadget(rc, "Use metaserver", args, i);
!    XtAddCallback(toggle, XmNvalueChangedCallback, _usemetaCB, True);
     XtManageChild(toggle);
     _toggle_meta = toggle;
  
***************
*** 321,327 ****
     }
     toggle = XmCreateToggleButtonGadget(rc, "Use resource server-list", 
        args, i);
!    XtAddCallback(toggle, XmNvalueChangedCallback, usemetaCB, False);
     XtManageChild(toggle);
     _toggle_resource = toggle;
  
--- 398,404 ----
     }
     toggle = XmCreateToggleButtonGadget(rc, "Use resource server-list", 
        args, i);
!    XtAddCallback(toggle, XmNvalueChangedCallback, _usemetaCB, False);
     XtManageChild(toggle);
     _toggle_resource = toggle;
  
***************
*** 334,340 ****
     }
     _showzero = XmCreateToggleButtonGadget(commandw, "Show empty servers",
        args, i);
!    XtAddCallback(_showzero, XmNvalueChangedCallback, showCB, 0);
     XtManageChild(_showzero);
  
     if(_localRes.use_serverlist)
--- 411,417 ----
     }
     _showzero = XmCreateToggleButtonGadget(commandw, "Show empty servers",
        args, i);
!    XtAddCallback(_showzero, XmNvalueChangedCallback, _showCB, 0);
     XtManageChild(_showzero);
  
     if(_localRes.use_serverlist)
***************
*** 349,355 ****
  	 XtSetArg(args[i], XmNset, False);
        toggle = XmCreateToggleButtonGadget(commandw, "Use cyborg",
  	 args, i);
!       XtAddCallback(toggle, XmNvalueChangedCallback, borgCB, 0);
        XtManageChild(toggle);
     }
  
--- 426,432 ----
  	 XtSetArg(args[i], XmNset, False);
        toggle = XmCreateToggleButtonGadget(commandw, "Use cyborg",
  	 args, i);
!       XtAddCallback(toggle, XmNvalueChangedCallback, _borgCB, 0);
        XtManageChild(toggle);
     }
  
***************
*** 357,391 ****
  
     /* frame around message window -- kludge actually */
     i=0;
     XtSetArg(args[i], XmNshadowThickness, 0);	i++;
!    frame = XmCreateFrame(mainw, "text_frame", args, i);
!    XtManageChild(frame);
  
     /* message window */
     i=0;
!    XtSetArg(args[i], XmNeditMode, XmMULTI_LINE_EDIT);	i++;
     textw = XmCreateScrolledText(frame, "text", args, i);
     XtManageChild(textw);
  
     _globals.textw = textw;
  
     /* tell mainw which is message window */
     i=0;
     XtSetArg(args[0], XmNmessageWindow, frame);		i++;
     XtSetValues(mainw, args, i);
  
     /* set other main window areas */
     XmMainWindowSetAreas(mainw, menu_bar,
!       commandw, NULL, NULL, _workarea);
     XtManageChild(mainw);
     XtRealizeWidget(app_shell);
  
!    message("%s\n", rcsid);
  
!    XtAppMainLoop(app_context);
  }
  
! Widget createHelp(par)
     
     Widget	par;
  {
--- 434,504 ----
  
     /* frame around message window -- kludge actually */
     i=0;
+ #ifdef NO_MW
+    /*
+    XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET);	i++;
+    XtSetArg(args[i], XmNtopWidget, mainw);			i++;
+    */
+    XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM);		i++;
+    XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM);	i++;
+    XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM);	i++;
+ #endif
     XtSetArg(args[i], XmNshadowThickness, 0);	i++;
!    frame = XmCreateFrame(
! #ifdef NO_MW
! 			top_form,
! #else
! 			mainw, 
! #endif
! 					"text_frame", args, i);
  
     /* message window */
     i=0;
!    XtSetArg(args[i], XmNeditMode, XmMULTI_LINE_EDIT);			i++;
!    /*
!    XtSetArg(args[i], XmNrows, _localRes.alt_program?8:4);		i++;
!    */
     textw = XmCreateScrolledText(frame, "text", args, i);
     XtManageChild(textw);
  
     _globals.textw = textw;
  
+    XtManageChild(menu_bar);		/* menu bar */
+    XtManageChild(commandw);		/* command section */
+    XtManageChild(_server_workarea);	/* form work area */
+    XtManageChild(frame);		/* text widget */
+ 
+ #ifndef NO_MW
     /* tell mainw which is message window */
     i=0;
     XtSetArg(args[0], XmNmessageWindow, frame);		i++;
     XtSetValues(mainw, args, i);
+ #else
+    i=0;
+    XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET);	i++;
+    XtSetArg(args[i], XmNbottomWidget, frame);		i++;
+    XtSetValues(mainw, args, i);
+ #endif
  
     /* set other main window areas */
     XmMainWindowSetAreas(mainw, menu_bar,
!       commandw, NULL, NULL, _server_workarea);
! 
     XtManageChild(mainw);
+ 
+ #ifdef NO_MW
+    XtManageChild(top_form);
+ #endif
+ 
     XtRealizeWidget(app_shell);
  
!    message("XNetrekM 1.%d \n", PATCHLEVEL);
  
!    XtAppMainLoop(_globals.app_context);
  }
  
! static Widget 
! _createHelp(par)
     
     Widget	par;
  {
***************
*** 429,444 ****
  
  /* metaserver */
  
! void createServerButtons()
  {
     register	i, j;
     Widget	vert = NULL;
     Widget	title;
!    Widget	parent = _workarea;
     Arg		args[16];
     XmString	name;
     ServerList	dummy;
!    Widget	entry_list[INITIAL_SERVER_ENTRIES * ENTRY_WIDGETS];
     int		e = 0;
  
     name = XmStringCreateLtoR("SERVER", XmSTRING_DEFAULT_CHARSET);
--- 542,558 ----
  
  /* metaserver */
  
! static void 
! _createServerButtons()
  {
     register	i, j;
     Widget	vert = NULL;
     Widget	title;
!    Widget	parent = _server_workarea;
     Arg		args[16];
     XmString	name;
     ServerList	dummy;
!    Widget	entry_list[INITIAL_SERVER_ENTRIES * /* xx */8];
     int		e = 0;
  
     name = XmStringCreateLtoR("SERVER", XmSTRING_DEFAULT_CHARSET);
***************
*** 451,457 ****
--- 565,573 ----
     _title = title;	/* needed later */
     XtManageChild(title);
     XmStringFree(name);
+    _globals.entry_widgets ++;
  
+ #ifdef SHOWPORT
     name = XmStringCreateLtoR("PORT", XmSTRING_DEFAULT_CHARSET);
     i=0;
     XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM);		i++;
***************
*** 462,467 ****
--- 578,585 ----
     title = XmCreateLabel(parent, "port_title", args, i);
     XtManageChild(title);
     XmStringFree(name);
+    _globals.entry_widgets ++;
+ #endif
  
     name = XmStringCreateLtoR("PLAYERS", XmSTRING_DEFAULT_CHARSET);
     i=0;
***************
*** 473,478 ****
--- 591,597 ----
     title = XmCreateLabel(parent, "players_title", args, i);
     XtManageChild(title);
     XmStringFree(name);
+    _globals.entry_widgets ++;
  
     name = XmStringCreateLtoR("TIME", XmSTRING_DEFAULT_CHARSET);
     i=0;
***************
*** 485,569 ****
     XtManageChild(title);
     XmStringFree(name);
     vert = title;
  
     _numServers = 0;
  
     if(_localRes.use_serverlist){
        (void)getResourceServerList(_serverList, &_numServers);
     }
     else {
        (void)getServers(_serverList, &_numServers);
     }
  
!    boundcheck(_numServers, MAX_SERVERS, "Max number of servers");
  
     for(j=0; j< _numServers; j++){
!       vert = createEntry(parent, &_serverList[j], &_serverWList[j], vert, j);
     }
  
!    /* create some dummies */
!    strcpy(dummy.server, "XX");
!    strcpy(dummy.port, "XX");
!    strcpy(dummy.players, "XX");
!    strcpy(dummy.time, "XX");
!    for(; j< INITIAL_SERVER_ENTRIES - _numServers; j++){
!       vert = createEntry(parent, &dummy, &_serverWList[j], vert, j);
!       entry_list[e++] = _serverWList[j].serverW;
!       entry_list[e++] = _serverWList[j].portF;
!       entry_list[e++] = _serverWList[j].playersF;
!       entry_list[e++] = _serverWList[j].timeF;
!       entry_list[e++] = _serverWList[j].pingW;
!       /* since we're going to unmanage them as soon as we're done */
!       _serverWList[j].managed = False;
!    }
! 
!    if(e)
        XtUnmanageChildren(entry_list, e);
  }
  
! int updateServerButtons()
  {
     register	i, j;
  
     Widget	fromV = NULL;
!    Widget	parent = _workarea;
     int		prevN = _numServers;
     Widget	*manage_list, *unmanage_list;
     int		ml=0, uml=0;
  
     if(_localRes.use_serverlist){
!       if(getResourceServerList(_serverList, &_numServers) < 0)
  	 return -1;
     }
     else {
        if(getServers(_serverList, &_numServers) < 0){
  	 return -1;
        }
     }
  
!    boundcheck(_numServers, MAX_SERVERS, "Max number of servers");
  
     manage_list = (Widget *) malloc(sizeof(Widget) * _numServers * 
!       ENTRY_WIDGETS);
!    unmanage_list = (Widget *) malloc(sizeof(Widget) * prevN * ENTRY_WIDGETS);
  
!    XtUnmanageChild(_workarea);
  
     for(j=0; j< _numServers; j++){
        if(_serverWList[j].realized){
  	 /* change label */
! 	 changeLabels(_serverList[j].server, _serverWList[j].serverW);
! 	 changeLabels(_serverList[j].port, _serverWList[j].portW);
! 	 changeLabels(_serverList[j].players, _serverWList[j].playersW);
! 	 changeLabels(_serverList[j].time, _serverWList[j].timeW);
  
  	 if(!_serverWList[j].managed){
  	    _serverWList[j].managed = True;
  	    manage_list[ml++] = _serverWList[j].serverW;
  	    manage_list[ml++] = _serverWList[j].portF;
  	    manage_list[ml++] = _serverWList[j].playersF;
  	    manage_list[ml++] = _serverWList[j].timeF;
  	    manage_list[ml++] = _serverWList[j].pingW;
  	 }
        }
        else {
--- 604,712 ----
     XtManageChild(title);
     XmStringFree(name);
     vert = title;
+    _globals.entry_widgets ++;
  
+    /* ping button */
+    _globals.entry_widgets ++;
+ 
+    if(_localRes.alt_program)
+       _globals.entry_widgets ++;
+ 
     _numServers = 0;
  
     if(_localRes.use_serverlist){
+       /* xx: fix */
        (void)getResourceServerList(_serverList, &_numServers);
     }
     else {
+       /* xx: fix */
        (void)getServers(_serverList, &_numServers);
     }
  
!    _boundCheck(_numServers, MAX_SERVERS, "xnetrekm: Max number of servers");
  
     for(j=0; j< _numServers; j++){
!       vert = _createEntry(parent, &_serverList[j], &_serverWList[j], vert, j);
     }
  
!    if(j < INITIAL_SERVER_ENTRIES){
!       /* create some dummies */
!       strcpy(dummy.server, "XX");
!       strcpy(dummy.port, "XX");
!       strcpy(dummy.players, "XX");
!       strcpy(dummy.time, "XX");
!       for(; j< INITIAL_SERVER_ENTRIES - _numServers; j++){
! 	 vert = _createEntry(parent, &dummy, &_serverWList[j], vert, j);
! 	 entry_list[e++] = _serverWList[j].serverW;
! #ifdef SHOWPORT
! 	 entry_list[e++] = _serverWList[j].portF;
! #endif
! 	 entry_list[e++] = _serverWList[j].playersF;
! 	 entry_list[e++] = _serverWList[j].timeF;
! 	 entry_list[e++] = _serverWList[j].pingW;
! 	 /* since we're going to unmanage them as soon as we're done */
! 	 _serverWList[j].managed = False;
!       }
        XtUnmanageChildren(entry_list, e);
+    }
  }
  
! static int 
! _updateServerButtons()
  {
     register	i, j;
  
     Widget	fromV = NULL;
!    Widget	parent = _server_workarea;
     int		prevN = _numServers;
     Widget	*manage_list, *unmanage_list;
     int		ml=0, uml=0;
  
     if(_localRes.use_serverlist){
!       if(getResourceServerList(_serverList, &_numServers) < 0){
! 	 _numServers = prevN;	/* leave previous */
  	 return -1;
+       }
     }
     else {
        if(getServers(_serverList, &_numServers) < 0){
+ 	 _numServers = prevN;   /* leave previous */
  	 return -1;
        }
     }
+    if(_localRes.debug)
+       printf("got %d servers\n", _numServers);
  
!    _boundCheck(_numServers, MAX_SERVERS, "xnetrekm: Max number of servers");
  
     manage_list = (Widget *) malloc(sizeof(Widget) * _numServers * 
!       _globals.entry_widgets);
!    unmanage_list = (Widget *) malloc(sizeof(Widget) * prevN * 
!       _globals.entry_widgets);
  
!    XtUnmanageChild(_server_workarea);
  
     for(j=0; j< _numServers; j++){
        if(_serverWList[j].realized){
  	 /* change label */
! 	 _changeLabels(_serverList[j].server, _serverWList[j].serverW);
! #ifdef SHOWPORT
! 	 _changeLabels(_serverList[j].port, _serverWList[j].portW);
! #endif
! 	 _changeLabels(_serverList[j].players, _serverWList[j].playersW);
! 	 _changeLabels(_serverList[j].time, _serverWList[j].timeW);
  
  	 if(!_serverWList[j].managed){
  	    _serverWList[j].managed = True;
  	    manage_list[ml++] = _serverWList[j].serverW;
+ #ifdef SHOWPORT
  	    manage_list[ml++] = _serverWList[j].portF;
+ #endif
  	    manage_list[ml++] = _serverWList[j].playersF;
  	    manage_list[ml++] = _serverWList[j].timeF;
  	    manage_list[ml++] = _serverWList[j].pingW;
+ 	    if(_localRes.alt_program)
+ 	       manage_list[ml++] = _serverWList[j].altPW;
  	 }
        }
        else {
***************
*** 570,577 ****
  	 if(j == 0)
  	    fromV = _title;
  	 else
! 	    fromV = _serverWList[j-1].portF;
! 	 (void)createEntry(parent, &_serverList[j], &_serverWList[j], fromV,
  	    j);
        }
     }
--- 713,720 ----
  	 if(j == 0)
  	    fromV = _title;
  	 else
! 	    fromV = _serverWList[j-1].playersF;
! 	 (void)_createEntry(parent, &_serverList[j], &_serverWList[j], fromV,
  	    j);
        }
     }
***************
*** 581,608 ****
  	 _serverWList[j].managed = False;
  	 if(!_serverWList[j].serverW) abort();		/* debug */
  	 unmanage_list[uml++] = _serverWList[j].serverW;
  	 unmanage_list[uml++] = _serverWList[j].portF;
  	 unmanage_list[uml++] = _serverWList[j].playersF;
  	 unmanage_list[uml++] = _serverWList[j].timeF;
  	 unmanage_list[uml++] = _serverWList[j].pingW;
        }
     }
  
     if(ml){
!       if(ml >= _numServers * ENTRY_WIDGETS) abort();	/* safeguard */
        XtManageChildren(manage_list, ml);
        free((char *) manage_list);
     }
     if(uml){
!       if(uml >= prevN * ENTRY_WIDGETS) abort();		/* safeguard */
        XtUnmanageChildren(unmanage_list, uml);
        free((char *) unmanage_list);
     }
!    XtManageChild(_workarea);
     return 0;
  }
  
! Widget createEntry(parent, e, ew, fv, index)
  
     Widget	parent;
     ServerList	*e;
--- 724,756 ----
  	 _serverWList[j].managed = False;
  	 if(!_serverWList[j].serverW) abort();		/* debug */
  	 unmanage_list[uml++] = _serverWList[j].serverW;
+ #ifdef SHOWPORT
  	 unmanage_list[uml++] = _serverWList[j].portF;
+ #endif
  	 unmanage_list[uml++] = _serverWList[j].playersF;
  	 unmanage_list[uml++] = _serverWList[j].timeF;
  	 unmanage_list[uml++] = _serverWList[j].pingW;
+ 	 if(_localRes.alt_program)
+ 	    unmanage_list[uml++] = _serverWList[j].altPW;
        }
     }
  
     if(ml){
!       if(ml > _numServers * _globals.entry_widgets) abort();	/* safeguard */
        XtManageChildren(manage_list, ml);
        free((char *) manage_list);
     }
     if(uml){
!       if(uml > prevN * _globals.entry_widgets) abort();		/* safeguard */
        XtUnmanageChildren(unmanage_list, uml);
        free((char *) unmanage_list);
     }
!    XtManageChild(_server_workarea);
     return 0;
  }
  
! static Widget 
! _createEntry(parent, e, ew, fv, index)
  
     Widget	parent;
     ServerList	*e;
***************
*** 614,620 ****
     Arg		args[16];
     XmString	name;
     Widget	sname, sport, splayers, stime, sping,
! 		frame1,frame2,frame3;
  
     ew->realized = True;
     ew->managed = True;
--- 762,768 ----
     Arg		args[16];
     XmString	name;
     Widget	sname, sport, splayers, stime, sping,
! 		frame1,frame2,frame3, saltp;
  
     ew->realized = True;
     ew->managed = True;
***************
*** 628,637 ****
     XtSetArg(args[i], XmNrecomputeSize, False);		i++;
     sname = XmCreatePushButton(parent, "server", args, i);
     ew->serverW = sname;
!    XtAddCallback(sname, XmNactivateCallback, callCB, index);
     XtManageChild(sname);
     XmStringFree(name);
  
     i=0;
     XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET);     i++;
     XtSetArg(args[i], XmNtopWidget, fv);                      i++;
--- 776,788 ----
     XtSetArg(args[i], XmNrecomputeSize, False);		i++;
     sname = XmCreatePushButton(parent, "server", args, i);
     ew->serverW = sname;
!    XtAddCallback(sname, XmNactivateCallback, _callCB, index);
     XtManageChild(sname);
     XmStringFree(name);
  
+ #ifdef SHOWPORT
+    /* port */
+ 
     i=0;
     XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET);     i++;
     XtSetArg(args[i], XmNtopWidget, fv);                      i++;
***************
*** 641,647 ****
     XtManageChild(frame1);
     ew->portF = frame1;
  
-    /* port */
  
     if(e->port[0] == '\0')
        strcpy(e->port, " ");	/* xx */
--- 792,797 ----
***************
*** 655,660 ****
--- 805,813 ----
     ew->portW = sport;
     XtManageChild(sport);
     XmStringFree(name);
+ #else
+    frame1 = sname;
+ #endif
  
     i=0;
     XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET);     i++;
***************
*** 713,729 ****
     sping = XmCreatePushButton(parent, "ping", args, i);
     XtManageChild(sping);
     ew->pingW = sping;
!    XtAddCallback(sping, XmNactivateCallback, pingCB, index);
  
!    return frame1;
  }
  
! void changeLabels(s, w)
  
     char		*s;
     Widget	w;
  {
     XmString	name;
  
     if(!s || *s == '\0')
        s = " ";		/* xx */
--- 866,903 ----
     sping = XmCreatePushButton(parent, "ping", args, i);
     XtManageChild(sping);
     ew->pingW = sping;
!    XtAddCallback(sping, XmNactivateCallback, _pingCB, index);
  
!    if(_localRes.alt_program){
! 
!       i=0;
! 
!       XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET);     i++;
!       XtSetArg(args[i], XmNtopWidget, fv);                      i++;
!       XtSetArg(args[i], XmNrecomputeSize, False);		i++;
!       XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET);    i++;
!       XtSetArg(args[i], XmNleftWidget, sping);                  i++;
!       XtSetArg(args[i], XmNleftOffset, 6);			i++;
!       saltp = XmCreatePushButton(parent, baseName(_localRes.alt_program), 
! 	 args, i);
! 
!       XtManageChild(saltp);
!       ew->altPW = saltp;
!       XtAddCallback(saltp, XmNactivateCallback, _altCB, index);
!    }
! 
!    return frame2;
  }
  
! static void 
! _changeLabels(s, w)
  
     char		*s;
     Widget	w;
  {
     XmString	name;
+    Arg		args[2];
+    register	i;
  
     if(!s || *s == '\0')
        s = " ";		/* xx */
***************
*** 730,744 ****
     
     name = XmStringCreateLtoR(s, XmSTRING_DEFAULT_CHARSET);
  
!    XtVaSetValues(w, XmNlabelString, name, NULL);
     XmStringFree(name);
  }
  
  
  /* callbacks */
  
- static void helpCB(w, client_data, call_data)
- 
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
--- 904,922 ----
     
     name = XmStringCreateLtoR(s, XmSTRING_DEFAULT_CHARSET);
  
!    i=0;
!    XtSetArg(args[i], XmNlabelString, name);	i++;
!    XtSetValues(w, args, i);
! 
     XmStringFree(name);
  }
  
  
  /* callbacks */
+ /*ARGSUSED*/
+ static void 
+ _helpCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
***************
*** 746,752 ****
     XtManageChild(_helpw);
  }
  
! static void exitCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
--- 924,932 ----
     XtManageChild(_helpw);
  }
  
! /*ARGSUSED*/
! static void 
! _exitCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
***************
*** 756,762 ****
  }
  
  
! static void updateCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
--- 936,944 ----
  }
  
  
! /*ARGSUSED*/
! static void 
! _updateCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
***************
*** 764,774 ****
  {
     if(_localRes.use_serverlist)
        return;
! 
!    (void)updateServerButtons();
  }
  
! static void callCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
--- 946,960 ----
  {
     if(_localRes.use_serverlist)
        return;
!    
!    XtSetSensitive(w, False);
!    (void)_updateServerButtons();
!    XtSetSensitive(w, True);
  }
  
! /*ARGSUSED*/
! static void 
! _callCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
***************
*** 780,796 ****
     startNetrek(&_serverList[index]);
  }
  
! static void usemetaCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
  {
     if((Boolean) client_data){
        if(!_localRes.use_serverlist)
  	 return;
        _localRes.use_serverlist = False;
!       if(updateServerButtons() < 0){
  	 XmToggleButtonGadgetSetState(_toggle_resource, True, False);
  	 XmToggleButtonGadgetSetState(_toggle_meta, False, False);
  	 _localRes.use_serverlist = True;
--- 966,987 ----
     startNetrek(&_serverList[index]);
  }
  
! /*ARGSUSED*/
! static void 
! _usemetaCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
  {
+    XtSetSensitive(_toggle_resource, False);
+    XtSetSensitive(_toggle_meta, False);
+ 
     if((Boolean) client_data){
        if(!_localRes.use_serverlist)
  	 return;
        _localRes.use_serverlist = False;
!       if(_updateServerButtons() < 0){
  	 XmToggleButtonGadgetSetState(_toggle_resource, True, False);
  	 XmToggleButtonGadgetSetState(_toggle_meta, False, False);
  	 _localRes.use_serverlist = True;
***************
*** 804,810 ****
        if(_localRes.use_serverlist)
  	 return;
        _localRes.use_serverlist = True;
!       if(updateServerButtons() < 0){
  	 XmToggleButtonGadgetSetState(_toggle_resource, False, False);
  	 XmToggleButtonGadgetSetState(_toggle_meta, True, False);
  	 _localRes.use_serverlist = False;
--- 995,1001 ----
        if(_localRes.use_serverlist)
  	 return;
        _localRes.use_serverlist = True;
!       if(_updateServerButtons() < 0){
  	 XmToggleButtonGadgetSetState(_toggle_resource, False, False);
  	 XmToggleButtonGadgetSetState(_toggle_meta, True, False);
  	 _localRes.use_serverlist = False;
***************
*** 816,824 ****
  	 XtSetSensitive(_showzero, False);
        }
     }
  }
  
! static void showCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
--- 1007,1020 ----
  	 XtSetSensitive(_showzero, False);
        }
     }
+ 
+    XtSetSensitive(_toggle_resource, True);
+    XtSetSensitive(_toggle_meta, True);
  }
  
! /*ARGSUSED*/
! static void 
! _showCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
***************
*** 829,850 ****
     if(_localRes.use_serverlist)
        return;
  
!    if(updateServerButtons() < 0); /* TODO */
  }
  
! static void pingCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
  {
!    FILE	*mi, *my_popen();
     static char	buf[256],
  		line1[80],
  		line2[80];
     int index = (int) client_data;
!    char	*sr, *getNumeric(), *findEntry(),	/* connect.c */
! 	 *strdup();
     int		err;
  
     message("Pinging %s ...", _serverList[index].server);
--- 1025,1049 ----
     if(_localRes.use_serverlist)
        return;
  
!    XtSetSensitive(w, False);
!    if(_updateServerButtons() < 0); /* TODO */
!    XtSetSensitive(w, True);
  }
  
! /*ARGSUSED*/
! static void 
! _pingCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
  {
!    FILE		*mi;
     static char	buf[256],
  		line1[80],
  		line2[80];
     int index = (int) client_data;
!    char		*sr;
     int		err;
  
     message("Pinging %s ...", _serverList[index].server);
***************
*** 863,869 ****
        _localRes.pingsize, _localRes.numpings);
     if(_localRes.debug)
        printf("%s\n", buf);
!    mi = my_popen(buf, "r");
     if(!mi){
        error("ping command to \"%s\" failed.\n", sr);
        free(sr);
--- 1062,1068 ----
        _localRes.pingsize, _localRes.numpings);
     if(_localRes.debug)
        printf("%s\n", buf);
!    mi = myPopen(buf, "r");
     if(!mi){
        error("ping command to \"%s\" failed.\n", sr);
        free(sr);
***************
*** 877,900 ****
     do {
        strncpy(line1, line2, 79);
        strncpy(line2, buf, 79);
!    }while(fgets(buf, 254, mi));
  
!    my_pclose(mi);
     message("\n%s", line1);
     message("%s", line2);
  }
  
! static void borgCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
  {
     _localRes.use_borg = !_localRes.use_borg;
  }
  
! static void usage(name, args)
  
     String       name, *args;
  {
     static char *help_message[] = {
--- 1076,1172 ----
     do {
        strncpy(line1, line2, 79);
        strncpy(line2, buf, 79);
!    } while(fgets(buf, 254, mi));
  
!    myPclose(mi);
     message("\n%s", line1);
     message("%s", line2);
  }
  
! /*ARGSUSED*/
! static void 
! _altCB(w, client_data, call_data)
  
     Widget	w;
     XtPointer	client_data;
     XtPointer	call_data;
  {
+    int		index = (int) client_data;
+    FILE		*pi;
+    char		*sr;
+    int		err;
+    char		buf[256];
+ 
+    message("%s ...", _localRes.alt_program);
+ 
+    sr = getNumeric(_serverList[index].server);
+    if(!sr){
+       /* name lookup failed, try the serverAddr resource */
+       sr = findEntry(_serverList[index].server, _localRes.serveraddress_map, 
+ 		     &err);
+       /* skip errors for now */
+       if(!sr)
+ 	 sr = strdup(_serverList[index].server);
+    }
+ 
+    sprintf(buf, "exec %s %s %s", _localRes.alt_program, sr,
+       _serverList[index].port);
+ 
+    if(_localRes.debug)
+       printf("%s\n", buf);
+ 
+    pi = myPopen(buf, "r");
+    if(!pi){
+       error("\"%s\" command failed.\n", buf);
+       free(sr);
+       return;
+    }
+    free(sr);
+ 
+    while(fgets(buf, 254, pi)){
+       message("%s", buf);
+    }
+    pclose(pi);
+ }
+ 
+ /*ARGSUSED*/
+ static void 
+ _borgCB(w, client_data, call_data)
+ 
+    Widget	w;
+    XtPointer	client_data;
+    XtPointer	call_data;
+ {
     _localRes.use_borg = !_localRes.use_borg;
  }
  
! /*ARGSUSED*/
! static XtEventHandler
! _refreshOnDeiconify(w, client_data, ev, cd)
  
+    Widget	w;
+    XtPointer	client_data;
+    XEvent	*ev;
+    Boolean	*cd;
+ {
+    if(_localRes.use_serverlist)
+       return;
+    
+    if(time(NULL) - _globals.last_refresh < (_localRes.min_autorefresh*60))
+       /* too soon */
+       return;
+    
+    if(ev->type == MapNotify && _localRes.refresh_on_deiconify){
+       XtSetSensitive(_refresh, False);
+       (void)_updateServerButtons();
+       XtSetSensitive(_refresh, True);
+    }
+ }
+ 
+ 
+ static void 
+ _usage(name, args)
+ 
     String       name, *args;
  {
     static char *help_message[] = {
***************
*** 914,920 ****
           args++;
     }
  
!    fprintf(stderr, "\nusage: %s [options ...]\n", name);
     for(cpp = help_message; *cpp; cpp++)
        fprintf(stderr, "%s\n", *cpp);
     exit(1);
--- 1186,1192 ----
           args++;
     }
  
!    fprintf(stderr, "\nusage: %s [options ...] [toolkitoptions ...]\n", name);
     for(cpp = help_message; *cpp; cpp++)
        fprintf(stderr, "%s\n", *cpp);
     exit(1);
***************
*** 921,927 ****
  }
  
  /* eliminate defunct processes */
! reaper(sig)
  
     int  sig;
  {
--- 1193,1200 ----
  }
  
  /* eliminate defunct processes */
! static void
! _reaper(sig)
  
     int  sig;
  {
***************
*** 931,943 ****
  	;
  }
  
! boundcheck(n, limit, s)
  
     int		n, limit;
     char		*s;
  {
     if(n >= limit){
!       fprintf(stderr, "%s limit exceeded at %d\n", limit);
        exit(1);
     }
  }
--- 1204,1217 ----
  	;
  }
  
! static void
! _boundCheck(n, limit, s)
  
     int		n, limit;
     char		*s;
  {
     if(n >= limit){
!       fprintf(stderr, "%s limit exceeded at %d\n", s, limit);
        exit(1);
     }
  }
*** xnetrekm.h	Sun Jul  5 16:25:33 1992
--- /i0/dh/ua/hadley/alternate/net/xnetrekm/xnetrekm.h	Tue Aug 11 01:44:36 1992
***************
*** 37,49 ****
  		netrekbinary_map,
  		borgbinary_map,
  		borgrc_map,
! 		serveraddress_map;
  } Resources;
  
  typedef struct {
     Display	*display;
     char		*program;
!    char		metaserver[MAX_SERVERNAME];	/* xx */
!    char		telnet_com[256];
     Widget	textw, errorw;
  } Globals;
--- 37,74 ----
  		netrekbinary_map,
  		borgbinary_map,
  		borgrc_map,
! 		serveraddress_map,
! 		preferred_serverlist;
!    String	alt_program;
!    Boolean	use_timeserver;
!    Boolean	refresh_on_deiconify;
!    int		min_autorefresh;
  } Resources;
  
  typedef struct {
+    XtAppContext	app_context;
     Display	*display;
     char		*program;
!    char		metaserver[MAX_SERVERNAME];
!    int		metaserver_port;
     Widget	textw, errorw;
+    int		num_preferred;
+    String	*preferred_serverlist;	/* array version of resource */
+    int		entry_widgets;
+    long		last_refresh;
  } Globals;
+ 
+ extern char	*strdup();
+ 
+ extern void 	starNetrek();			/* connect.c */
+ extern char	*getNumeric();			/* connect.c */
+ extern void	error();			/* mesg.c */
+ extern void	message();			/* mesg.c */
+ extern int	getServers();			/* metaserver.c */
+ extern int	getResourceServerList();	/* metaserver.c */
+ extern FILE	*myPopen();			/* popen.c */
+ extern int	myPclose();			/* popen.c */
+ extern char	*findEntry();			/* strutil.c */
+ extern char	**getPreferredServerList();	/* strutil.c */
+ extern char	*homeExpand();			/* strutil.c */
+ extern char	*baseName();			/* strutil.c */
