v12i055: xrlogin - X client for creating rlogin and telnet sessions, Part01/01

William LeFebvre phil at eecs.nwu.edu
Wed Apr 24 17:00:26 AEST 1991


Submitted-by: phil at eecs.nwu.edu (William LeFebvre)
Posting-number: Volume 12, Issue 55
Archive-name: xrlogin/part01

echo 'Start of distribution file xrlogin.shar:'
echo 'Extracting README...'
sed 's/^X//' > README << '/'
Xxrlogin - an X tool to create rlogin and telnet windows
X
Xxrlogin is an X tool that creates rlogin and telnet sessions on demand.
XEach session is given its own "xterm" window.  When the remote session
Xis terminated, the window itself will be removed.  The window's title
Xis set to the name of the remote machine for easy identification.
X
XAny user can maintain his own list of favorite hosts by placing them
Xin a file called ".xrlogin" in his home directory.  Xrlogin will put
Xthis list in a scrollable area and allow the user to select from it.
X
XWhen the user requests a connection, xrlogin first checks to see if
Xthe host is up and reachable.  It does this by using the program
Xcalled "tryhost" included in the distribution.  This program takes an
XInternet address (in decimal!) and a timeout value as arguments,
Xattempts to connect to the TCP "discard" port of the remote end, and
Xwrites to standard error any problems it encounters (including
Xtimeout).  It will exit with non-zero status if anything went wrong.
XXrlogin starts "tryhost" as a subprocess and displays the error
Xmessage when "tryhost" exits with non-zero status.
X
XI originally used "ping" to perform this function, but some (if not
Xall) versions of "ping" keep trying in certain situations, such as
X"network is unreachable".  Xrlogin gives the system manager and the
Xuser the ability to choose the "ping" program through the option
X"-ping" and through the resource manager.  If the named program does
Xnot end with "/tryhost", then the arguments provided will be (in this
Xorder) hostname and timeout.  If it does end with "/tryhost", then the
Xarguments will be IP address (in decimal) and timeout.
X
XTo compile and install xrlogin, first edit Imakefile.  Set the
Xvariable "Ping" (near the top) to the full path name of the ping
Xprogram you want to use by default.  If you want to use "tryhost"
X(this is recommended), then put it in a lib directory somewhere since
Xit is not really intended to be used by mere mortals.  If you do not
Xwant to use "tryhost", then comment out the line "#define UseTryhost"
Xand set "Ping" to point to the pinging program of your choice.
X
XAfter editing Imakefile, merely run "xmkmf" and "make install".
X
XI hope you like this program as much as I do.  Send comments, bugs,
Xfixes, etc., to the address below.
X
X		William LeFebvre
X		phil at eecs.nwu.edu
/
echo 'Extracting xrlogin.man...'
sed 's/^X//' > xrlogin.man << '/'
X.TH XRLOGIN 1 Local
X.UC 4
X.SH NAME
Xxrlogin \- X client for creating rlogin and telnet sessions
X.SH SYNOPSIS
X.B xrlogin
X[
X.B -hostfile
X.I file
X] [
X.B -timeout
X.I seconds
X] [
X.B -ping
X.I file
X]
X.SH DESCRIPTION
X.B Xrlogin
Xis an X client that makes the initiation of
X.I rlogin
Xand
X.I telnet
Xsessions easier.  Each remote login is created with its own window running
X.IR xterm .
XThe window and icon titles are set to be the name of the remote machine.
XWhen the remote session is terminated (such as when the remote user
Xlogs out) the window is removed.
X.PP
XBefore the connection is attempted, the machine name is checked for
Xexistence, and the remote machine is probed via
Xan external program to make sure that it is up and reachable.
XThis program is typically one that is included as part of the
X.I xrlogin
Xsource, but a program such as
X.IR ping (8)
Xcan also be used.
X.PP
XA file of frequently used hostnames can be created and maintained by
Xthe user.  These names will appear in a scrollable widget
Xat the right of the window.  A connection can be initiated to any of these
Xhosts by merely clicking on the appropriate name.  By default this file
Xis called
X.B .xrlogin
Xin the user's home directory.
X.SH OPTIONS
X.TP
X.B \-hostfile 
XSpecifies the name of the file that contains commonly used hostnames.
X.TP
X.B \-timeout
XSpecifies the number of seconds for
Xthe pinging program
Xto attempt to reach the machine.  If no answer is received in that
Xtime, ping will declare the machine down.  The default is 5.
X.TP
X.B \-ping
XSpecifies the program to use to check for connectivity.  It usually
Xdefaults to something called
X.IR tryhost ,
Xwhich was written specifically for
X.IR xrlogin .
XAny executable that is specified here must be prepared to accept two
Xarguments:  a host name and an integer timeout value (in that order).
XIt should exit with a non-zero status and a message on standard error
Xif it detected that something was amiss.
X.SH AUTHOR
XWilliam LeFebvre, Northwestern University
X.SH FILES
X.DT
X~/.xrlogin	list of commonly used hostnames
X/usr/lib/X11/xrlogin/tryhost	xrlogin-specific ping-like program
X.br
X.SH "SEE ALSO"
X.IR xterm (1),
X.IR rlogin (1),
X.IR telnet (1),
X.IR ping (8).
/
echo 'Extracting Imakefile...'
sed 's/^X//' > Imakefile << '/'
X/* xrlogin -- Imakefile */
X
X/*
X * Set "Ping" to suit your tastes.
X * Make sure that the directory exists before installation!
X * $(LIBDIR) is set by imake to point to the standard X library (this
X * is usually "/usr/lib/X11").
X */
XPing = $(LIBDIR)/xrlogin/tryhost
X/*
X * If you do not want to use the "tryhost" program included in this
X * distribution, then comment out the next line.
X */
X#define UseTryhost
X
XLOCAL_LIBRARIES = XawClientLibs
XDEPLIBS = XawClientDepLibs
XPROGRAMS = xrlogin tryhost
XSRCS = xrlogin.c tryhost.c
X
X#ifdef UseTryhost
XAllTarget($(PROGRAMS))
X#endif
X
XNormalProgramTarget(xrlogin, xrlogin.o, /**/, $(LOCAL_LIBRARIES), /**/)
XNormalProgramTarget(tryhost, tryhost.o, /**/, /**/, /**/)
X
XSpecialObjectRule(.o, .h, /**/)
XSpecialObjectRule(xrlogin.o, /**/, '-DDEFAULT_PING="$(Ping)"')
X
XDependTarget()
X
XInstallProgram(xrlogin, $(BINDIR))
X#ifdef UseTryhost
XInstallProgram(tryhost, $(Ping))
X#endif
XInstallAppDefaults(XRlogin)
XInstallManPage(xrlogin, $(MANDIR))
/
echo 'Extracting XRlogin.ad...'
sed 's/^X//' > XRlogin.ad << '/'
X! Widget heirarchy:
X!
X! Name			Class
X! ---------------------------
X! form			Form
X!   label		Label
X!   host		AsciiText
X!   message		Label
X!   type		Label
X!   telnet		Toggle
X!   rlogin		Toggle
X!   username		Label
X!   user		AsciiText
X!   quit		Command
X!   connect		Command
X!   hostview		Viewport
X!     hostlist		List
X
X*Label.borderWidth: 0
X*Toggle.shapeStyle: Rectangle
X
X*label.label: Host name
X*label.Edge: ChainTop
X
X*host.width: 151
X*host.resize: width
X*host.resizable: True
X*host.top: ChainTop
X*host.bottom: ChainTop
X*host.left: ChainTop
X*host.right: ChainLeft
X
X*message.borderWidth: 0
X*message.justify: left
X*message.label:
X*message.width: 230
X*message.Edge: ChainTop
X
X*type.label: Connection type:
X*type.Edge: ChainTop
X
X*telnet.label: telnet
X*telnet.Edge: ChainTop
X
X*rlogin.label: rlogin
X*rlogin.horizDistance: 0
X*rlogin.Edge: ChainTop
X
X*username.label: Remote Username:
X*username.Edge: ChainTop
X
X*user.Edge: ChainTop
X*user.width: 102
X
X*quit.label: Quit
X*quit.accelerators: #override Ctrl<Key>C:   set() notify() unset()
X*quit.Edge: ChainTop
X
X*connect.label: Connect
X*connect.horizDistance: 23
X*connect.accelerators: #override <Key>Return:   set() notify() unset()
X*connect.Edge: ChainTop
X
X*hostlist.top: ChainTop
X*hostlist.bottom: ChainBottom
X*hostlist.right: ChainRight
X*hostlist.translations: #override <Btn1Down>,<Btn1Up>: Set() Notify() \n\
X		<Btn1Up>(2):  Unset() Connect()
X
X! the fromHoriz and fromVert constraints on the hostview widget are
X! intentionally specified here.  This gives the user the freedom to
X! place the widget pretty much wherever he or she pleases.
X
X*hostview.height: 111
X*hostview.horizDistance: 8
X*hostview.top: ChainTop
X*hostview.left: ChainLeft
X*hostview.right: ChainLeft
X*hostview.fromHoriz: host
X*hostview.useRight: true
X
/
echo 'Extracting xrlogin.c...'
sed 's/^X//' > xrlogin.c << '/'
X/*
X * xrlogin - X based interface to rlogin, allowing interactive entry
X *           of hostname
X *
X * Copyright (c) 1991 by William LeFebvre
X *
X * This software is free and may be freely redistributed, but the author
X * requires that this entire comment area remain intact.
X */
X
X#define VERSION 1
X#include "patchlevel.h"
X
X#define TRYHOST "./tryhost"
X
X#define IP_ADDR_LEN  4
X
X#define FlushDisplay      (XFlush(XtDisplay(context->toplevel)))
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/wait.h>
X#include <sys/stat.h>
X#include <netdb.h>
X
X/* includes for widgets go here */
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/AsciiText.h>
X#include <X11/Xaw/Toggle.h>
X#include <X11/Xaw/List.h>
X#include <X11/Xaw/Viewport.h>
X
X#include <X11/Xaw/Cardinals.h>
X
X#include "xrlogin.h"
X
Xchar copyright[] = "xrlogin, Copyright (c) 1991 by William LeFebvre";
X
Xextern int sys_nerr;
Xextern char *sys_errlist[];
Xextern int errno;
X
XWidget wg_connect;
X
XAppData app_data;
X
X/* the context gets passed to the callbacks so that they have handles for
X   all the other widgets, including the toplevel, and the application context.
X */
X
Xtypedef struct Context {
X    XtAppContext app_context;
X    Widget       toplevel;
X    Widget       host;
X    Widget       message;
X    Widget       telnet;
X    Widget       user;
X} *Context;
X
X/* * * * MESSAGE HANDLING ROUTINES * * * */
X
X/* show_message(wg, msg) - display "msg" in the message area */
X
XXtIntervalId message_intid = NULL;
X
Xshow_message(context, msg)
X
XContext context;
Xchar *msg;
X
X{
X    static char message_area[1024];
X    static Arg nargs[] =
X    {
X	{XtNlabel, (XtArgVal)message_area},
X    };
X
X    /* make sure there isn't a timer pending */
X    if (message_intid != NULL)
X    {
X	XtRemoveTimeOut(message_intid);
X	message_intid = NULL;
X    }
X
X    strcpy(message_area, msg);
X    XtSetValues(context->message, nargs, XtNumber(nargs));
X}
X
Xclear_message(context, intid)
X
XContext context;
XXtIntervalId *intid;
X
X{
X    message_intid = NULL;
X    show_message(context, "");
X}
X
Xexpire_message(context)
X
XContext context;
X
X{
X    /* make sure the message expires after a certain period of time */
X    /* 8 seconds ought to be good */
X    message_intid = XtAppAddTimeOut(context->app_context,
X				    8*1000, clear_message, context);
X}
X
X
X/* * * * * * * */
X
Xchar *tryhost(name, ipaddr, timeout, ping)
X
Xchar *name;
Xu_long ipaddr;
Xint timeout;
Xchar *ping;
X
X{
X    union wait st;
X    int pfd[2];
X    register char *p;
X    register int i;
X    register int child;
X    static char msg[1025];
X    static char addr[20];
X
X    /* convert timeout delay into a string (so we can pass it to execl) */
X    sprintf(msg, "%d", timeout);
X
X    /* do the same with the internet address */
X    sprintf(addr, "%ld", ipaddr);
X
X    /* determine type of ping to use and remember in "i" */
X    if ((p = rindex(ping, '/')) == NULL)
X    {
X	p = ping;
X    }
X    else
X    {
X	p++;
X    }
X    i = strcmp(p, "tryhost") == 0;
X
X    /* launch a "ping", capture the output, and look at the return status */
X    pipe(pfd);
X    if ((child = vfork()) == 0)
X    {
X	/* child process */
X	dup2(pfd[1], 1);
X	dup2(pfd[1], 2);
X	close(pfd[0]);
X	close(pfd[1]);
X	execl(ping, p, i ? addr : name, msg, 0);
X	_exit(100);
X    }
X
X    /* parent */
X    close(pfd[1]);
X    while ((i = wait(&st)) != child)
X    {
X	if (i == -1)
X	{
X	    close(pfd[0]);
X	    return(sys_errlist[errno >= sys_nerr ? 0 : errno]);
X	}
X    }
X    if (WIFEXITED(st) && st.w_retcode == 0)
X    {
X	close(pfd[0]);
X	return(NULL);
X    }
X    else
X    {
X	i = read(pfd[0], msg, sizeof(msg)-1);
X	close(pfd[0]);
X	if (i == -1)
X	{
X	    return(sys_errlist[errno >= sys_nerr ? 0 : errno]);
X	}
X	msg[i] = '\0';
X	if ((p = index(msg, '\n')) != NULL)
X	{
X	    *p = '\0';
X	}
X	return(msg);
X    }
X}
X
X/* Callbacks for command widgets: */
X
Xcmd_quit()
X
X{
X    exit(0);
X}
X
Xcmd_connect(w, context, call)
X
XWidget w;
XContext context;
Xcaddr_t call;
X
X{
X    register int num;
X    register int isrlogin;
X    struct hostent *hent;
X    char *reach;
X    char *cmd;
X    unsigned int addrparts[4];
X    unsigned int address;
X    char *opt1 = NULL;         /* optional argument to xterm */
X    char *opt2 = NULL;         /* optional argument to xterm */
X    static String str;
X    static String name;
X    static Arg nargs[] =
X    {
X	{XtNstring, NULL},
X    };
X
X    /* update the display */
X    FlushDisplay;
X
X    /* get the desired host name */
X    nargs[0].value = (XtArgVal)&name;
X    XtGetValues(context->host, nargs, XtNumber(nargs));
X
X    /* if hostname is null, be friendly */
X    if (name[0] == '\0')
X    {
X	show_message(context, "No host name specified!");
X	return;
X    }
X
X    /* get the connection type, which will be the command to use */
X    if ((cmd = XawToggleGetCurrent(context->telnet)) == NULL)
X    {
X	show_message(context, "No connection type selected.");
X	return;
X    }
X
X    /* rlogin requires special handling */
X    isrlogin = strcmp(cmd, "rlogin") == 0;
X
X    /* is it just an IP address? */
X    num = sscanf(name, "%u.%u.%u.%u",
X		 &addrparts[0],
X		 &addrparts[1],
X		 &addrparts[2],
X		 &addrparts[3]);
X    if (num == 4)
X    {
X	/* internet number specified---convert to integer */
X	address = (addrparts[0] << 24) |
X	          (addrparts[1] << 16) |
X		  (addrparts[2] << 8)  |
X		  addrparts[3];
X
X	/* use telnet since rlogin doesn't grok IP numbers */
X	if (isrlogin)
X	{
X	    cmd = "telnet";
X	    show_message(context, "Using telnet");
X	    FlushDisplay;
X	}
X    }
X    else
X    {
X	/* try to get its IP address */
X	if ((hent = gethostbyname(name)) == NULL)
X	{
X	    show_message(context, "That host name is not known.");
X	    return;
X	}
X	if (hent->h_length != IP_ADDR_LEN)
X	{
X	    show_message(context, "Unexpected address length");
X	    return;
X	}
X	bcopy(hent->h_addr_list[0], &address, IP_ADDR_LEN);
X
X	/* if rlogin, get and use username */
X	if (isrlogin)
X	{
X	    nargs[0].value = (XtArgVal)&str;
X	    XtGetValues(context->user, nargs, XtNumber(nargs));
X	    if (str[0] != '\0')
X	    {
X		opt1 = "-l";
X		opt2 = (char *)str;
X	    }
X	}
X    }
X
X    /* make sure it is up and reachable */
X    show_message(context, "Connecting...");
X    FlushDisplay;
X    if ((reach = tryhost(name, address,
X			 app_data.timeout,
X			 app_data.ping)) != NULL)
X    {
X	show_message(context, reach);
X    }
X    else     /* everything is okay, initiate a connection */
X    {
X	if (vfork() == 0)
X	{
X	    /* child */
X	    execl("/usr/bin/X11/xterm", "xterm",
X		  "-T", name,
X		  "-e", cmd, name, opt1, opt2, 0);
X	    _exit(100);
X	}
X
X	/* set the message to expire */
X	expire_message(context);
X    }
X}
X
Xcmd_select(w, context, list)
X
XWidget w;
XContext context;
XXawListReturnStruct *list;
X
X{
X    static Arg nargs[] =
X    {
X	{XtNstring, NULL},
X    };
X
X    /* retrieve the selected hostname and jam it into host widget */
X    nargs[0].value = (XtArgVal)(list->string);
X    XtSetValues(context->host, nargs, XtNumber(nargs));
X
X    /* unhighlight the widget */
X    XawListUnhighlight(w);
X
X    /* erase the message area (since the host widget changed) */
X    show_message(context, "");
X}
X
X/* Other Callbacks: */
X
X/* this callback is called whenever a text widget changes */
X
Xvoid widget_changed(widget, context, call)
X
XWidget widget;
XContext context;
Xcaddr_t call;
X
X{
X    /* clear out message area */
X    show_message(context, "");
X}
X
X/* Actions: */
X
Xact_connect(w, event, params, num_params)
X
XWidget w;
XXEvent *event;
XString *params;
Xint    num_params;
X
X{
X    XtCallCallbacks(wg_connect, XtNcallback, NULL);
X}
X
Xstatic XtActionsRec actionsTable[] =
X{
X    {"Connect", (XtActionProc)act_connect},
X    {NULL, NULL}
X};
X
X/* Initialization stuff: */
X
X/* init_textwidget:  set a text widget to call "widget_changed" when 
X   it is changed */
X
Xinit_textwidget(context, widget)
X
XContext context;
XWidget widget;
X
X{
X    static Widget source;
X    static Arg warg[] =
X    {
X	{XtNtextSource, (XtArgVal)&source},
X    };
X
X    /* we have to retrieve the textsource widget and add the callback
X       to that widget's callback list!  */
X
X    XtGetValues(widget, warg, 1);
X    XtAddCallback(source, XtNcallback, widget_changed, context);
X}
X
Xint filesize(name)
X
Xchar *name;
X
X{
X    struct stat st;
X
X    return(stat(name, &st) == 0 ? (int)st.st_size : 0);
X}
X
X/* 
X *  build_hosts_list(filename) - read the specified file and build a list
X *        of hosts to choose from suitable for a List widget.
X */
X
Xchar **build_hosts_list(filename)
X
Xchar *filename;
X
X{
X    register int size;
X    register int fd;
X    register char *ptr;
X    register char *tptr;
X    register char **pptr;
X    char *hostdata = NULL;
X    char **hosts = NULL;
X    static char buff[1024];
X
X    /* if filename doesn't start with '/', prepend $HOME/ to it */
X    if (filename[0] != '/')
X    {
X	strcpy(buff, getenv("HOME"));
X	strcat(buff, "/");
X	strcat(buff, filename);
X	filename = buff;
X    }
X
X    if ((size = filesize(filename)) > 0)
X    {
X	if ((hostdata = (char *)malloc(size)) != NULL)
X	{
X	    if ((fd = open(filename, O_RDONLY)) >= 0)
X	    {
X		/* read the entire file */
X		size = read(fd, hostdata, size);
X		close(fd);
X
X		/* determine number of lines */
X		/* reuse "fd" as a temporary */
X		fd = 0;
X		ptr = hostdata;
X		while (--size >= 0)
X		{
X		    if (*ptr++ == '\n')
X		    {
X			fd++;
X		    }
X		}
X
X		/* guard against lines == 0 */
X		if (fd > 0)
X		{
X		    /* allocate array of pointers */
X		    if ((hosts = (char **)malloc((fd + 1) * sizeof(char *))) != NULL)
X		    {
X			/* build array of pointers */
X			pptr = hosts;
X			size = fd;
X			ptr = hostdata;
X			while (--size >= 0)
X			{
X			    /* put pointer to this line in array */
X			    *pptr++ = ptr;
X
X			    /* find end of line */
X			    while (*ptr++ != '\n');
X
X			    /* back up over trailing spaces */
X			    tptr = ptr - 1;
X			    while (*--tptr == ' ');
X
X			    /* terminate string after last meaningful char */
X			    *(tptr+1) = '\0';
X			}
X			*pptr = NULL;
X		    }
X		}
X	    }
X	}
X    }
X
X    /* if build was unsuccessful, free buffer */
X    if (hosts == NULL && hostdata != NULL)
X    {
X	free(hostdata);
X    }
X
X    /* done */
X    return(hosts);
X}
X
Xmain(argc, argv)
X
Xint argc;
Xchar *argv[];
X
X{
X    XtAppContext app_con;
X    XtWidgetGeometry wgeo;
X    Widget toplevel;
X    Widget wg_form, wg_label, wg_host, wg_quit, wg_message;
X    Widget wg_type, wg_telnet, wg_rlogin, wg_hostlist, wg_hostview;
X    Widget wg_user, wg_username;
X    struct Context context;
X    char **hosts;
X
X    /* X initialization */
X    toplevel = XtAppInitialize(&app_con, "XRlogin",
X			       options, XtNumber(options),
X			       &argc, argv, NULL,
X			       NULL, ZERO);
X
X    /* syntax check */
X    if (argc > 1)
X    {
X	usage_message();
X	exit(1);
X    }
X
X    /* add our specific actions */
X    XtAppAddActions(app_con, actionsTable, XtNumber(actionsTable));
X
X    /* get application resources */
X    XtGetApplicationResources(toplevel,
X			      &app_data,
X			      resources,
X			      XtNumber(resources),
X			      NULL, ZERO);
X
X    /* build the hosts list from the file in the home directory */
X    hosts = build_hosts_list(app_data.hostfile);
X
X    /* create all the widgets */
X    wg_form = XtCreateManagedWidget("form", formWidgetClass, toplevel,
X				    NULL, ZERO);
X
X    wg_label = XtVaCreateManagedWidget("label", labelWidgetClass, wg_form,
X				       NULL);
X
X    wg_host = XtVaCreateManagedWidget("host", asciiTextWidgetClass, wg_form,
X				      XtNfromHoriz, (XtArgVal)wg_label,
X				      XtNeditType, (XtArgVal)XawtextEdit,
X				      NULL);
X    init_textwidget(&context, wg_host);
X
X    wg_message = XtVaCreateManagedWidget("message", labelWidgetClass, wg_form,
X					 XtNfromVert, (XtArgVal)wg_label,
X					 NULL);
X
X    wg_type = XtVaCreateManagedWidget("type", labelWidgetClass, wg_form,
X				      XtNfromVert, (XtArgVal)wg_message,
X				      NULL);
X
X    wg_telnet = XtVaCreateManagedWidget("telnet", toggleWidgetClass, wg_form,
X					XtNfromVert, (XtArgVal)wg_message,
X					XtNfromHoriz, (XtArgVal)wg_type,
X					NULL);
X
X    wg_rlogin = XtVaCreateManagedWidget("rlogin", toggleWidgetClass, wg_form,
X					XtNfromVert, (XtArgVal)wg_message,
X					XtNfromHoriz, (XtArgVal)wg_telnet,
X					XtNradioGroup, (XtArgVal)wg_telnet,
X					XtNstate, (XtArgVal)True,
X					NULL);
X
X    wg_username = XtVaCreateManagedWidget("username", labelWidgetClass,
X					   wg_form,
X					   XtNfromVert, (XtArgVal)wg_type,
X					   NULL);
X
X    wg_user = XtVaCreateManagedWidget("user", asciiTextWidgetClass, wg_form,
X				      XtNfromHoriz, (XtArgVal)wg_username,
X				      XtNfromVert, (XtArgVal)wg_type,
X				      XtNeditType, (XtArgVal)XawtextEdit,
X				      NULL);
X
X    wg_quit = XtVaCreateManagedWidget("quit", commandWidgetClass, wg_form,
X				      XtNfromVert, (XtArgVal)wg_username,
X				      NULL);
X
X    wg_connect = XtVaCreateManagedWidget("connect", commandWidgetClass, wg_form,
X					 XtNfromHoriz, (XtArgVal)wg_quit,
X					 XtNfromVert, (XtArgVal)wg_username,
X					 NULL);
X
X    /* create list widget for hostname choices only if we need to */
X    if (hosts != NULL)
X    {
X	/* create the viewport (with scrollbar) */
X	wg_hostview = XtVaCreateManagedWidget("hostview",
X					      viewportWidgetClass, wg_form,
X#ifdef notdef
X					      XtNfromHoriz, (XtArgVal)wg_message,
X					      XtNfromVert, (XtArgVal)wg_host,
X#endif
X					      XtNallowVert, (XtArgVal)True,
X					      NULL);
X
X	/* create the list widget itself */
X	wg_hostlist = XtVaCreateManagedWidget("hostlist",
X					      listWidgetClass, wg_hostview,
X					      XtNverticalList, (XtArgVal)True,
X					      XtNlist, hosts,
X					      XtNdefaultColumns, (XtArgVal)1,
X					      XtNforceColumns, (XtArgVal)True,
X					      NULL);
X
X	/* add a callback for selection */
X	XtAddCallback(wg_hostlist, XtNcallback, cmd_select, &context);
X
X	/* get the intended width of list widget */
X	XtQueryGeometry(wg_hostlist, NULL, &wgeo);
X
X	/* add width sufficient for scrollbar */
X	/* 14 is MAGIC:  should be taken from resources */
X	/* set viewport width */
X	XtVaSetValues(wg_hostview, XtNwidth, (XtArgVal)(wgeo.width + 14),
X		      NULL);
X    }
X
X    /* build the context structure used by all the callbacks */
X    context.app_context = app_con;
X    context.toplevel = toplevel;
X    context.host = wg_host;
X    context.message = wg_message;
X    context.telnet = wg_telnet;
X    context.user = wg_user;
X
X    XtAddCallback(wg_quit, XtNcallback, cmd_quit, NULL);
X    XtAddCallback(wg_connect, XtNcallback, cmd_connect, &context);
X
X    /* install the accelerators for the buttons */
X    XtInstallAllAccelerators(wg_form, wg_connect);
X    XtInstallAllAccelerators(wg_form, wg_quit);
X    XtInstallAllAccelerators(wg_host, wg_connect);
X    XtInstallAllAccelerators(wg_host, wg_quit);
X    XtInstallAllAccelerators(wg_user, wg_connect);
X    XtInstallAllAccelerators(wg_user, wg_quit);
X
X    XtRealizeWidget(toplevel);
X    XtAppMainLoop(app_con);
X}
X
Xusage_message()
X
X{
X    fprintf(stderr, "\
Xxrlogin version %d.%d, Copyright (c) 1991 by William LeFebvre,\n\
Xxrlogin understands all X toolkit options plus:\n\
X\t-hostfile file     file containing popular host names\n\
X\t-timeout time      time to wait for remote end to answer\n",
X	    VERSION, PATCHLEVEL);
X}
/
echo 'Extracting xrlogin.h...'
sed 's/^X//' > xrlogin.h << '/'
X/* xrlogin.h - include file for xrlogin */
X
Xtypedef struct {
X    String hostfile;
X    String ping;
X    int timeout;
X} AppData, *AppDataPtr;
X
Xstatic XtResource resources[] = {
X    {
X	"hostfile",
X	"Hostfile",
X	XtRString,
X	sizeof(String),
X	XtOffset(AppDataPtr, hostfile),
X	XtRString,
X	".xrlogin"
X    },
X    {
X	"ping",
X	"Ping",
X	XtRString,
X	sizeof(String),
X	XtOffset(AppDataPtr, ping),
X	XtRString,
X	DEFAULT_PING
X    },
X    {
X	"timeout",
X	"Timeout",
X	XtRInt,
X	sizeof(int),
X	XtOffset(AppDataPtr, timeout),
X	XtRString,
X	"5"
X    }
X};
X
Xstatic XrmOptionDescRec options[] = {
X    {"-hostfile", "*hostfile", XrmoptionSepArg, NULL},
X    {"-ping", "*ping", XrmoptionSepArg, NULL},
X    {"-timeout", "*timeout", XrmoptionSepArg, NULL}
X};
/
echo 'Extracting patchlevel.h...'
sed 's/^X//' > patchlevel.h << '/'
X#define PATCHLEVEL 2
/
echo 'Extracting tryhost.c...'
sed 's/^X//' > tryhost.c << '/'
X/*
X * tryhost -- a simple type of "ping"
X * 
X * Copyright (c) 1991 by William LeFebvre
X *
X * This software is free and may be freely redistributed, but the author
X * requires that this entire comment area remain intact.
X *
X * Written by William LeFebvre specifically for "xrlogin".
X *
X * syntax: tryhost IP-number timeout
X *
X *	"IP-number" is the internet address to try, and is in DECIMAL!
X *		Decimal was chosen to make it quick to encode and decode.
X *	"timeout" is the number of seconds to try before giving up.
X */
X
X#include <stdio.h>
X#include <errno.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X
X/*
X *  We do these as predefined constants because:  (1) we are after speed and
X *  (2) they won't be changing very often, if at all.
X */
X
X#define  TCP            6
X#define  UDP           17
X#define  DISCARD_PORT   9
X
Xextern int errno;
Xextern char *sys_errlist[];
Xextern int sys_nerr;
X
Xtimeout()
X
X{
X    fputs("Connection timed out\n", stderr);
X    exit(1);
X}
X
Xchar *err_msg()
X
X{
X    if (errno >= 0 && errno < sys_nerr)
X    {
X	return(sys_errlist[errno]);
X    }
X    else
X    {
X	return(sys_errlist[0]);
X    }
X}
X
Xmain(argc, argv)
X
Xint argc;
Xchar *argv[];
X
X{
X    int s;
X    int len;
X    struct sockaddr_in addr, host;
X
X    if (argc < 3)
X    {
X	fputs("invalid arguments", stderr);
X	exit (1);
X    }
X
X    if ((s = socket(PF_INET, SOCK_STREAM, TCP)) < 0)
X    {
X	perror("socket");
X	exit (1);
X    }
X
X    bzero(&host, sizeof(host));
X
X    alarm(atoi(argv[2]));
X    signal(SIGALRM, timeout);
X
X    host.sin_family = AF_INET;
X    host.sin_port = htons(DISCARD_PORT);
X    host.sin_addr.s_addr = htonl(atoi(argv[1]));
X    if (connect(s, &host, sizeof(host)) < 0)
X    {
X	if (errno != ECONNREFUSED)
X	{
X	    fprintf(stderr, "%s\n", err_msg());
X	    exit(1);
X	}
X	/* else:  if the machine can refuse, then it must be alive! */
X    }
X
X    close(s);
X    exit(0);
X}
/
echo 'Distribution file xrlogin.shar complete.'


--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources.x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list