Xterminals and dxsession (summary - long)

Michael C. B. Ashley mcba at newt.phys.unsw.OZ.AU
Thu Mar 14 08:33:03 AEST 1991


A couple of weeks ago I asked 

| Has anyone managed to successfully run a number of Xterminals from a
| DECstation using dxsession? If so, could use PLEASE send me your
| /etc/ttys entries and any relevant setup files?
|
| I have my Xterminals 99% working, my remaining problem is that if you
| log into more than one Xterminal with the same username, then when you
| quit dxsession from one terminal it clobbers the window manager on the
| both terminals. This can cause major problems in our teaching labs where
| we have accounts used by many people. The documentation on dxsession is
| insufficiently detailed for me to work out what is wrong.
|
| Thanks!

I received a very helpful reply from Barry Davis <barry at ncd.com>
which enabled me to solve my problems.

The following setup will allow you to run a number of Xterminals
from a DECstation using dxsession. Each terminal will display the
DIGITAL login box, and behave just like the console. I have only
tried this with NCD 15b Xterminals (great little machines!).  The
system is a DS5000/200 running ULTRIX 4.0 with 88 MBytes of memory
and 23 Xterminals. There are no response problems and the system
runs like a rocket.
        
To begin with you add one entry in the /etc/ttys file for each
Xterminal.  I put the entries at the end of the file, and they should
look something like:

17 "/usr/bin/login -P /usr/local/ncd/Xprompter-ncd
    -C /usr/local/ncd/start-ncd -e" none on secure 
18 "/usr/bin/login -P /usr/local/ncd/Xprompter-ncd
    -C /usr/local/ncd/start-ncd -e" none on secure

(Note: this shows two entries. Each entry should be on a single line.)

These entries instruct init to invoke /usr/bin/login for each
terminal, with its stdin and stdout connected to
/usr/local/ncd/Xprompter-ncd (we shall see in a minute that this is a
script which starts up Xprompter for the terminal in question (which
results in a DIGITAL login box appearing)), and that when a login
succeeds, the script /usr/local/ncd/start-ncd is to be run (this
starts up dxsession). The "-e" switch enables an "extended protocol",
whatever that is (maybe it encrypts the password for transmission?).

The critical trick is that the first thing on the line ("17" and "18"
in the above examples) is sent to the scripts
/usr/local/ncd/Xprompter-ncd and /usr/local/ncd/start-ncd as an
argument, and it is this that enables these scripts to work out which
Xterminal to connect to. I am not sure what possible forms this first
argument can take, just choose something from which you can work out
the IP address of the Xterminal. Clearly there are special cases you
should avoid (e.g., tty01, ttyp0, and :0 (the console)).

You should also make an entry in /dev for each of the new "devices",
e.g.,

# cd /dev
# ln -s /dev/null 17
# ln -s /dev/null 18

or, maybe you could use the following 

# cd /dev
# ls -l /dev/null
crw-rw-rw-  1 root       3,   2 Feb 20 11:21 /dev/null
# mknod /dev/17 c 3 2
# chmod 666 /dev/17
# mknod /dev/18 c 3 2
# chmod 666 /dev/18
# ls -l /dev/null*

(Could someone advise me of the pros and cons of these approaches?)

The only reason that I add an entry to /dev is so that finger works
(otherwise it reports "can't stat device 17"). Presumably there are
other reasons to do this. Can someone offer advice?

Don't forget to do "kill -HUP 1" so that the entries in /etc/ttys
take effect.

Here are the other files that you need:

----------------------------------------------------------
/usr/local/ncd/Xprompter-ncd
#!/bin/sh
if [ $1 = "-e" ]
then
  shift
fi
DISPLAY=`grep '^'$1 /usr/local/ncd/ncdlist | awk '{print $2}'`
export DISPLAY
/usr/bin/Xprompter -e $DISPLAY

----------------------------------------------------------
/usr/local/ncd/start-ncd
#!/bin/sh
if [ $1 = "-e" ]
then
  shift
fi
DISPLAY=`grep '^'$1 /usr/local/ncd/ncdlist | awk '{print $2}'`
export DISPLAY
/usr/bin/dxsession $DISPLAY
/usr/local/ncd/stop-ncd -display $DISPLAY

----------------------------------------------------------
/usr/local/ncd/stop-ncd
#!/bin/sh
for i in `/usr/bin/X11/xlswins | grep -v '^   ' | awk '{print $1}'`
do
  /usr/bin/X11/xkill -id $i $@
done

----------------------------------------------------------

and the file /usr/local/ncd/ncdlist contains the correspondences
between the entries in /etc/ttys and the Xterminal addresses. For
example,

17    129.94.130.128:0
18    129.94.130.129:0

(you can use names rather than IP numbers if you want to).

When you successfully login, you are running "/usr/bin/dxsession
$DISPLAY" from the "/usr/local/ncd/start-ncd" script. When you logout
by choosing the "Quit" option from the "Session" menu of the "Session
Manager", the next line in the script is executed, which calls
"/usr/local/ncd/stop-ncd", which uses xkill to get rid of all your
remaining windows (otherwise the login box will not reappear). I'm a
bit worried about using xkill since the manual entry for it says
don't ever use it. The alternative is to let dxsession kill your
windows for you (this is what happens on the console), however,
dxsession does not appear to be intelligent enough to correctly
guess which windows to remove, and will happily kill window managers
that you may have running on other Xterminals. You persuade dxsession
not to kill your windows by giving it the argument $DISPLAY (actually
anything unique will do (I think)).

A final problem is what to do when a terminal fails to display a
login box.  I have only seen this occur if a user turns the terminal
off in the middle of a session, and then only rarely. Sometimes you
can fix this by using the "Restart Session" button from the NCD
Compose Setup main menu. Othertimes I have found that there is a
dxsession process still hanging which appears to ignore "Restart
Session", so you have to explicitly kill it. Rarely, the Xprompter
process itself needs to be killed and restarted. To allow users to
correct these problems even if they don't own the dxsession process
(e.g., the terminal was hung by someone who then walked off), I have
written the perl script which follows

/usr/local/bin/resetxterm.pl
#!/usr/local/bin/perl -w
print "This program will attempt to terminate your X session and
restore a DIGITAL login box. WARNING: you must run this program from
a Telnet Session created from the Main Menu that appears when you use
COMPOSE-F3. Also, you must only run this program from the X terminal
that you wish to restart.  If both of these conditions are met, type
\"yes\" to continue >";
chop($answer=<STDIN>);
if ($answer ne 'yes') {exit 0;}
$ENV{'IFS'} = '' if $ENV{'IFS'};
$ENV{'PATH'} = "/bin:/usr/bin:/usr/ucb/:/usr/local/bin";
open(TTY, '/usr/bin/tty|') || die "can't run tty!";
$tty = substr(<TTY>,8,2);
close(TTY);
open(W, '/usr/ucb/w|') || die "can't run w!";
$ip = 'invalid';
while(<W>) {
  if ($tty eq substr($_,9,2)) {
    $ip = substr($_,12,14);
    last;
    }
  }
close(W);
if (substr($ip,0,8) ne '129.94.1') {
  die "can't find the internet address for this X-terminal
  sorry, I can't help!";
  }
print "\nyour IP address appears to be $ip\n";
open(PS, "/bin/ps -ax|grep \"dxsession $ip\"|") 
  || die "can't run ps!";
$dxsession_pid='0';
while (<PS>) {
  if (/usr/) {
    print "the terminal is being controlled by the 
      following process\n$_";
    $dxsession_pid=substr($_,0,5);
    $pid=$dxsession_pid;
    $pid=~s/ //g;
    open(PS2, "/bin/ps -$pid|grep \"dxsession $ip\"|") 
      || die "can't run ps!";
    if ($dxsession_pid ne substr(<PS2>,0,5)) {
      print "hmm... the process appears to have vanished...\n";
      last;
      }
    print "now trying to kill the process...\n";
    kill 15, $dxsession_pid;
    sleep(5);
    kill 9, $dxsession_pid;
    last;
  }
}
close(PS);
close(PS2);
if ($dxsession_pid eq '0') {
  print "can't find the controlling dxsession for this X-terminal
maybe the problem is a stuck Xprompter ...\n";
  }
$Xprompter_pid = '0';
open(PS3, "/bin/ps -ax|grep \"/bin/Xprompter -e $ip\"|") 
  || die "can't run ps!";
while (<PS3>) {
  if (/usr/) {
    print "the terminal's Xprompter is being controlled 
      by the following process\n$_";
    $Xprompter_pid=substr($_,0,5);
    $pid=$Xprompter_pid;
    $pid=~s/ //g;
    open(PS4, "/bin/ps -$pid|grep \"/bin/Xprompter -e $ip\"|") 
      || die "can't run ps!";
    if ($Xprompter_pid ne substr(<PS4>,0,5)) {
      print "hmm... the process appears to have vanished...\n";
      last;
    }
    print "now trying to kill the process...\n";
    kill 15, $Xprompter_pid;
    last;
    }
  }
close(PS3);
close(PS4);
print "OK, I've done all that I can, click Main Menu, followed by
Done; the DIGITAL login box should appear shortly. If it doesn't, try
the Restart Session button in the Main Menu. As a last resort, try
turning the terminal off, leaving it for 30 seconds, and turning it
back on.

DON'T FORGET TO LOG OUT OF THIS TELNET SESSION WHEN YOU HAVE
FINISHED!!!\n";

-------------------------------------------------------------------------------

This script has to run setuid to root, so I call it with the
following program

main(argc,argv)
int argc;
char **argv;
{
  execv("/usr/local/bin/resetxterm.pl",argv);
}

the executable of this program is in /usr/local/bin/resetxterm with 
a protection mask of 4711, and owned by root.

A remaining problem is that the command "w" doesn't work out the
process idle time correctly and you get crazy answers like 20 hours
even though you have only been logged in for half an hour.

That's all folks! I hope that this has been useful to someone. If you
have any suggestions on how to improve this setup, or can correct my
possible misconceptions, please let me know.

Michael Ashley mcba at newt.phys.unsw.oz.au
Astrophysics Dept. / Uni of NSW / Sydney, Australia



More information about the Comp.unix.ultrix mailing list