#!/bin/sh # Some System V systems don't understand the #! construct. # If your system does understand it, put ": " at the beginning of the line. # XRSH_VER='xrsh version 5.8-amc3-draft1' # AMC XRSH_RCS='$Header: /usr/u/jjd/xrsh/RCS/xrsh.sh,v 1.12 1994/06/13 15:53:11 jjd Exp $' XRSH_TIME='Time-stamp: <94/06/13 11:43:59 jjd>' # # Copyright 1991 by James J. Dempsey # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, James J. Dempsey makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # /AMC\ # This is draft 1 of modification 3 of xrsh 5.8 by # Adam M. Costello # 16 Mar 1995 # All added/changed lines are marked by the string AMC, either as a # comment on the line itself, or as a pair of brackets like the two # surrounding this comment. # \AMC/ # # xrsh: start an X11 client on another host # # Usage: xrsh [-help] [-version ] [-l username] [-auth authtype] [-screen #] [-pass envlist] \ # [-debug] [-debug2] hostname [X-command [arguments...]] # # Example usage: xrsh expo.lcs.mit.edu xterm # # Runs the given command on another host with $DISPLAY set in the environment. # Handles authentication using xhost, xauth, or $XAUTHORITY (or none). # Xrsh is very careful not to leave any extra processes waiting # around on either machine for the client to exit. In order # to achieve this, csh is used on the remote host and all inputs # and outputs are redirected to /dev/null. # The -debug switch allows you to see errors, but doesn't worry about # leaving extra processes around. # The -debug2 switch sets -x so that you can see every command # executed by the script (very verbose) # The -l switch allows you to use a different login name on the # remote host. -l and its argument are passed directly to rsh. # The -help switch prints out the usage message. # The -screen switch allows you to start a client on a different screen. # If no X command is given, it defaults to xterm. This means that # 'xrsh remotehost' will start an xterm on remotehost. # If the given command is a path that ends in "xterm", it adds the # arguments "-name xterm-$hostname" where $hostname is the name # of the remote host. This allows you to customize your server's # xrdb database to set attributes, such as the window color, based # on the name of remote host. If you dislike this behaviour, specify # your own -name argument to xterm on the xrsh command line. # # Xrsh handles authentication based on the value of $XRSH_AUTH_TYPE or # the value of the -auth command line switch. The value can # be xhost, xauth, environment or none. It defaults to xhost. # xhost -- run xhost to enable the remote host to open window # run xhost on the host where the server is running # xhost-xterminal -- # run xhost to enable the remote host to open windows # run xhost on the host where xrsh was first run # xauth -- merge the auth entry from this host on the remote # host using xauth via rsh # environment -- pass the $XAUTHORITY environment variable from the # local host to the remote host so that a common # NFS accessable authority file can be used everywhere # none -- do nothing. Assume the user has handled authentication. # # If the environment variable XRSH_RSH_ERRORS is set to the name of a file, # any rsh errors will appear in that file on the remote host. # If that variable is unset, error messages will be thrown away unless # the -debug switch is given. (Note: don't use ~ in the filename # because it will expand to ~ on the local host, but try to put the # errors in that file on the remote host.) # # /AMC\ # If the environment variable XRSH_EXTRA_PATH is set, it will be # appended to PATH on the remote host in any rsh. If it is not # set, it will take on a default value (look for it below). The # final remote command will NOT inherit this augmented path; it # is used only to locate the remote command. Note that this # often solves the first two of the common problems listed below. # \AMC/ # # COMMON PROBLEMS: # * Make sure your PATH environment variable on the remote host is # set in your .cshrc or .bashrc so that rsh programs have # access to it. (/bin/sh and /bin/ksh users have a hard time # time here since their shells don't execute any init files # under rsh. One way to do this is to use the XRSH_ENVS_TO_PASS # environment variable to pass PATH to the remote shell. # Optionally, you can type a full path to xrsh. # E.g. xrsh remote-host /usr/bin/X11/xterm # # * Make sure your PATH environment variable on the remote host # includes the directory containing the X programs. This is # often /usr/bin/X11 or /usr/local/bin/X11. # * Make sure you have rsh configured to work on the remote host. # You can test this by typing: rsh remote-host echo '$PATH' # This will prove that rsh works and show you the PATH that # will be used on the remote host. If you get "Permission # denied." you probably need to update your ~/.rhosts file # on the remote host. See rlogin(1). # # Until X11R5, this command used to be called "xon". The name was # changed in order to be more descriptive, to have a name that better # matches its cousin (xrlogin) and to not collide with a similar command # written by Keith Packard distributed with X11R5. # # ACQUIRING XRSH: # # Check for new versions of xrsh via anonymous ftp to ftp.x.org under the # contrib subdirectory. Always do this before reporting a bug to see if # the bug has already been fixed. # # Written by Jim Dempsey with help from Stephen Gildea # based on an idea by Dave Mankins . # Some additional features due to dgreen@cs.ucla.edu, # "David B. Rosen" , Eero Simoncelli # and Martin Friedmann # # Originally written around 1987. # Last modification by jjd@bbn.com. # Version 5.1 of xrsh was distributed with X11R5. # initialize some variables default_auth_type=xhost # sites might want to change this authenv= foundarg= progname=`basename $0` rshoptions="" passenvs= # environment variables to pass along passenvs_raw= # passenvs without XRSH_EXTRA_PATH # AMC xhostvar= # used by auth type xhost-xterminal usage="usage: $progname [-help] [-version] [-l username] [-auth authtype] [-screen #] [-debug] [-debug2] host [cmd [args ...]]" if [ -z "$DISPLAY" ]; then echo "$progname: "'$DISPLAY must be set' 1>&2 ; exit 1 fi if [ -z "$XRSH_RSH_ERRORS" ]; then XRSH_RSH_ERRORS=/dev/null fi # /AMC\ if [ "${XRSH_EXTRA_PATH-nil}" = nil ]; then XRSH_EXTRA_PATH=/usr/bin/X11:/usr/local/bin/X11:/usr/X11/bin:/usr/X/bin:/pkg/X11/bin fi # \AMC/ # process command line arguments until [ "$foundarg" = "no" ] do foundarg=no case $1 in -version) echo "Version: ${XRSH_VER}" #echo "RCS info: ${XRSH_RCS}" # AMC #echo "Last saved: ${XRSH_TIME}" # AMC exit 0 ;; -debug) debug=t; foundarg=yes; shift; ;; -debug2) set -x; foundarg=yes; shift; ;; -help) echo $usage; exit 0; ;; -l) shift; rshoptions="-l $1"; foundarg=yes; shift; ;; -auth) shift; XRSH_AUTH_TYPE=$1; foundarg=yes; shift; ;; -pass) shift; XRSH_ENVS_TO_PASS=$1; foundarg=yes; shift; ;; -screen) shift; # this line was blatantly stolen from Keith Packard's xon DISPLAY=`echo $DISPLAY|sed 's/:\\([0-9][0-9]*\\)\\.[0-9]/:\1/'`.$1 foundarg=yes; shift; ;; esac done if [ "$#" = "0" ]; then echo $usage 1>&2; exit 1; fi clienthost="$1"; shift # The full remote host name (as full as possible) command=$1 if [ -z "$command" ]; then # default command to xterm if none specified command=xterm else shift fi # Grab the arguments to the command here so that we don't have to worry # about restoring them when doing IFS hacking below xcmdargs="$@" # Try to avoid running hostname. # Some shells set $HOST or $HOSTNAME automatically. localhost=${HOST-${HOSTNAME-`hostname`}} # The local host name # Remove domain part from hostname. # The following paragraph of IFS based code replaces sed and # runs faster because it doesn't fork. # clientshort is remote host name without domain #clientshort=`echo $clienthost | sed -e 's/\..*$//'` oldIFS=$IFS IFS=. set $clienthost clientshort=$1 IFS=$oldIFS # Find display host # The following paragraph of IFS based code replaces sed and # runs faster because it doesn't fork. #displayhost=`echo $DISPLAY | sed 's/:.*//'` oldIFS=$IFS IFS=: set $DISPLAY case "$#" in 1) displayhost=$localhost;; *) displayhost=$1;; esac IFS=$oldIFS case "$displayhost" in "unix"|"local"|"") displayhost=$localhost;; esac # People use the -name resource to specify host-specific resources # such as window color. if [ `basename "$command"` = "xterm" ]; then command="$command -name xterm-$clientshort -title 'xterm@$clientshort'" command="$command -n $clientshort" # AMC fi if [ $# -ge 1 ]; then command="$command $xcmdargs" fi # Some System V hosts have rsh as "restricted shell" and ucb rsh is remsh if [ -r /usr/bin/remsh ]; then rsh=remsh elif [ -f /usr/bin/rcmd ]; then # SCO Unix uses "rcmd" instead of rsh rsh=rcmd else rsh=rsh fi # Construct the new $DISPLAY for the remote client # The following paragraph of IFS based code replaces sed and # runs faster because it doesn't fork. It also handles the arp stuff. # newdisplay="`echo $DISPLAY | sed \"s/^[^:]*:/${localhost}:/\"`" oldIFS=$IFS IFS=: set $DISPLAY if [ $# = 2 ]; then shift fi case "$displayhost" in # AMC # If the remote host is the localhost, then don't put the hostname # in $DISPLAY and let X find the fastest display path "$clienthost") # AMC newdisplay=:$@ ;; # if a full internet domain name is used, set $DISPLAY # using IP address so remote host will be guaranteed return path # /AMC\ # First try to fully qualify whatever name is being used. [1-9]*) # IP address. Leave it. newdisplay="$displayhost:$@" ;; *) if [ -x /usr/sbin/nslookup ]; then nslookup=/usr/sbin/nslookup elif [ -x /usr/etc/nslookup ]; then nslookup=/usr/etc/nslookup elif [ -x /etc/nslookup ]; then nslookup=/etc/nslookup else nslookup=nslookup fi name=`$nslookup "$displayhost" 2>&1 | awk '$1 ~ /^[nN]ame:$/ { print $2; exit }'` if [ "$name" ]; then newdisplay="${name}:$@" else if [ -f /usr/sbin/arp ]; then arp=/usr/sbin/arp elif [ -f /usr/etc/arp ]; then arp=/usr/etc/arp elif [ -f /etc/arp ] ; then arp=/etc/arp else arp=arp fi address=`$arp $displayhost | awk '{ a = index($0, "("); b = index($0, ")"); if (a > 0 && b > a) print substr($0, a+1, b-a-1); }'` if [ "$address" ]; then newdisplay="$address:$@" else newdisplay="${displayhost}:$@" fi # \AMC/ fi ;; # A host in the local domain *) newdisplay="${displayhost}:$@" ;; esac IFS=$oldIFS # process env variables to pass early so that we can send them # in the xauth commands as well as the actual X client rsh command. # This is necessary for brain-dead shells like ksh which don't run # any init files to set the path properly. The user can instead # send PATH as an XRSH_ENVS_TO_PASS. # /AMC\ # But what if the path needed on the remote machine is nothing like the # path here? XRSH_EXTRA_PATH provides a way to augment the path on the # remote side just for the execution of $command. $command itself does # NOT inherit the augmented path. Preliminary commands like xhost and # xauth do, but so what? # \AMC/ for variable in $XRSH_ENVS_TO_PASS do if eval [ \""\${$variable-Xyzzy}"\" != "Xyzzy" ]; then # /AMC\ eval passenvs_raw="\"setenv $variable '\$$variable'; $passenvs_raw"\" # \AMC/ fi done # /AMC\ if [ "$XRSH_EXTRA_PATH" ]; then passenvs="setenv PATH '\${PATH}:$XRSH_EXTRA_PATH'; $passenvs_raw" else passenvs=$passenvs_raw fi # \AMC/ # Use $XRSH_AUTH_TYPE to determine whether to run xhost, xauth, # propagate $XAUTHORITY to the remote host, or do nothing case ${XRSH_AUTH_TYPE-$default_auth_type} in xhost) if [ "$newdisplay" != "$DISPLAY" ]; then # If run on the same host as server, allow remote host access X server. if [ "$debug" ]; then xhost +$clienthost else xhost +$clienthost > /dev/null 2>&1 fi else # If run on a different host as the server, use rsh to allow # access to the host in DISPLAY. xhostcmd="setenv DISPLAY $DISPLAY; exec xhost +$clienthost" if [ "$debug" ]; then # send $passenvs in case the user has a brain dead remote shell # and needs to be able to pass the PATH env var (e.g. ksh) echo "Executing \"xhost +$clienthost\" on $displayhost with DISPLAY=$DISPLAY" $rsh "$displayhost" exec /bin/csh -cf "\"$passenvs $xhostcmd\"" < /dev/null else $rsh "$displayhost" exec /bin/csh -cf "\"$passenvs $xhostcmd < /dev/null >& /dev/null\"" < /dev/null > /dev/null 2>&1 fi fi ;; xhost-xterminal) # If run on an X terminal, rsh to the XDMCP host to run xhost # if this is the first time, we are on the XDMCP host and # we can just run xhost. if [ "$XHOST" = "" ]; then xhostvar="setenv XHOST $localhost; " if [ "$debug" ]; then xhost +$clienthost else xhost +$clienthost > /dev/null 2>&1 fi else xhostvar="setenv XHOST $XHOST; " xhostcmd="setenv DISPLAY $DISPLAY; exec xhost +$clienthost" # send $passenvs in case the user has a brain dead remote shell # and needs to be able to pass the PATH env var (e.g. ksh) if [ "$debug" ]; then echo "Executing \"xhost +$clienthost\" on $XHOST with DISPLAY=$DISPLAY" $rsh "$XHOST" exec /bin/csh -cf "\"$passenvs $xhostcmd\"" < /dev/null else $rsh "$XHOST" exec /bin/csh -cf "\"$passenvs $xhostcmd < /dev/null >& /dev/null\"" > /dev/null < /dev/null 2>&1 fi fi ;; xauth) # the "xauth remove" is theoretically unnecessary below, # but due to a bug in the initial X11R5 (fixed in fix-09) xauth, # entries for MIT-MAGIC-COOKIE-1 get lost if # you do merge twice without the remove. The remove # command can be removed when xauth gets fixed. if [ "$debug" ]; then xauth extract - $newdisplay | \ $rsh $clienthost $rshoptions exec /bin/csh -cf "\"$passenvs xauth remove $newdisplay ; xauth merge -\"" else # Conditionalize this on $passenvs so that we don't pay the price # of forking a csh on the remote host if we don't need environment # variables evaluated. if [ "$passenvs" ]; then xauth extract - $newdisplay | \ $rsh $clienthost $rshoptions exec /bin/csh -cf "\"$passenvs xauth remove $newdisplay ; xauth merge -\"" >/dev/null 2>&1 else xauth extract - $newdisplay | \ $rsh $clienthost $rshoptions xauth remove $newdisplay \;xauth merge - >/dev/null 2>&1 fi fi ;; none) ;; environment) authenv="setenv XAUTHORITY $XAUTHORITY; " ;; *) echo -n "$progname: "'$XRSH_AUTH_TYPE must be set to "xhost", ' 1>&2 echo '"xhost-xterminal", "xauth", "environment" or left unset' 1>&2 exit 1 ;; esac # Do the real work using rsh. # Don't use -n to rsh because SG IRIX doesn't support it. # Use < /dev/null instead. tmpfile=xrsh-$$-$localhost # AMC if [ "$debug" ]; then echo "Executing \"$command\" on $clienthost with DISPLAY=$newdisplay" # /AMC\ # $rsh $clienthost $rshoptions /bin/csh -cf "\"setenv DISPLAY $newdisplay; $authenv $xhostvar $passenvs $command\"" < /dev/null redirect= # \AMC/ else # # The redirection inside the innermost quotes is done by csh. The outer # redirection is done by whatever shell the user uses on the remote end. # The inner redirection is necessary for an error log -- the outer # redirection is necessary to make sure that the local rsh doesn't hang around. # # The outermost < /dev/null is to simulate the -n argument to rsh which # we don't want to use for portability reasons. # # The three sets of redirections are for the local shell, the login shell # on the remote host and the csh on the remote host. # # We would like the last '>' to be '>&' or equivalent, but that would make this # code dependent on what flavor of shell the user uses on the remote host # # /AMC\ # exec $rsh $clienthost $rshoptions exec /bin/csh -cf "\"setenv DISPLAY $newdisplay; $authenv $xhostvar $passenvs exec $command < /dev/null >>& $XRSH_RSH_ERRORS \" < /dev/null > /dev/null " < /dev/null redirect="< /dev/null >>& $XRSH_RSH_ERRORS" # \AMC/ fi # /AMC\ # The redirection of the login shell on the remote host served no purpose # as far as I could tell, so I've eliminated it. # # Creating a temporary file to be passed to a Bourne shell on the remote # host servers two purposes: # # 1) $command now gets evaluated only by one remote sh instead of both # the remote login shell and the remote csh. This makes quoting # more possible. # # 2) Unlike csh, sh allows its own PATH to be altered without # propagating it to child processes. # $rsh $clienthost $rshoptions "exec /bin/csh -cf \"rm -f $tmpfile; \ cat > $tmpfile; setenv DISPLAY $newdisplay; $authenv $xhostvar \ $passenvs_raw exec /bin/sh $tmpfile $redirect\"" << !EOF! rm \$0 PATH=\$PATH:$XRSH_EXTRA_PATH exec $command !EOF! # \AMC/