nago updated: now correctly handles filenames with spaces There is a new version of the small Gopher client 'nago', with several improvements: file names with embedded spaces were not handled correctly, which is now solved; in directory listings (selector 1), the selector type is shown at the end of each line (except for i or 1 types), after a slash; the trailing line containing only a dot is removed from directory listings. The current version follows (also available in the 'scripts' section of my Gopherspace). Please note that the script contains strings with embedded TABs, and it relies on that - so make sure you do not save them converted into sequences of SPC! It may be better to get the script from the 'scripts' directory. #!/bin/sh # licenced under GPL 2005 Yargo C Bonetti CVSID='$Id: nago.sh,v 1.15 2010/01/29 00:07:49 yargo Exp $' # external programs pager=${PAGER:-more} pager=more browser=${BROWSER:-lynx -force_html} telnet=${TELNET:-telnet} #imgviewer=display imgviewer=echo #mync () { ${NETCAT:-/sys/pkg/sbin/nc} "$@" ; } #mync () { socat -t9 tcp4:$1:$2 - ; } mync () { read gf ; snarf "gopher://$1:$2/$gf" '-'; } STDHOME=sdf.lonestar.org/ # just in case somebody changes the standard... gopherport=70 gopherhome=${GOPHER_HOME:-$STDHOME} # temporary files tmpbase=${TEMP:-/tmp} tmpprefix=`basename $0`tmp dirtmp=$tmpbase/$tmpprefix.$$.dir ftmp=$tmpbase/$tmpprefix.$$.tmp stack=$tmpbase/$tmpprefix.$$.stack if [ "$1" = "" ] ; then cat <<EOH usage: $0 [-h|<server>] [<directory> <port>] where <server> is a server in gopherspace, <directory> a subdir on it, and <port> the port to connect to (default $gopherport) e.g: $0 sdf.lonestar.org /users/yargo -h uses environment variable GOPHER_HOME as starting point (currently $GOPHER_HOME), or if that is empty, $STDHOME (only default port $gopherport is supported, and must be a directory) Note: will not work for retrieving a file directly! (undefined behaviour) ($CVSID) EOH exit 1 fi rmexit () { rm -f $dirtmp $ftmp $stack ; exit $1 ; } # make sure temporary files are writable rm -f $dirtmp $ftmp $stack if ! echo test > $dirtmp ; then echo "** cannot write into temporary file $dirtmp - giving up!" rmexit 9 fi if ! echo test > $ftmp ; then echo "** cannot write into temporary file $ftmp - giving up!" rmexit 9 fi if ! echo test > $stack ; then echo "** cannot write into stack file $stack - giving up!" rmexit 9 fi if [ "$1" = "-h" ] ; then # remove / and all after s_ser=${gopherhome%%/*} # remove first / and all before, and prepend / again s_dir=/${gopherhome#*/} s_por=$gopherport else s_ser=$1 s_dir=/$2 s_por=${3:-$gopherport} fi # selector type: directory s_typ=1 echo "starting at $s_ser:$s_por$s_dir" # get a directory $s_dir from server $s_ser , port $s_por, # preprocess it, and store it getdir () { # get directory if echo "$s_dir" | mync "$s_ser" "$s_por" | sed -e 's/ then oldifs="$IFS"; IFS=' ' # line number counter ln=1 # add title = server directory, will also represent selectable line number echo " 0 $s_ser:$s_por $s_dir" >$dirtmp # now process every line in turn cat $ftmp | { while read ft rest ; do # test filetype=1st character case $ft in # i=fake, don't generate a number - note: there are TABs in the two strings! i*) echo ". $ft $rest" >>$dirtmp ;; # otherwise it is an entry which may be selected: prepend number, increment *) echo " $ln $ft $rest" >>$dirtmp ; ln=`expr $ln + 1` ;; esac done } IFS="$oldifs" else # cannot get directory, error return 1 fi } # definitions for actions: ACT_back=0 ACT_select=1 ACT_quit=2 ACT_other=3 # show directory (in $dirtmp), and return selection type, dir, server, port # and action in variables s_typ, s_dir, s_ser, s_por, s_act selectdir () { # take field 1&2 only, remove 1 char after first tab (filetype), store # (note TABs in sed argument) cat $dirtmp | cut -f 1-2 | sed -e 's/ \(.\)\(.*\)/ \2 \/\1/;s/ \/[.i1]$//' >$ftmp ln=X act=$ACT_select # repeat until legal linenumber given (note: 0 is legal!) while ! grep "^ $ln " $dirtmp >/dev/null ; do # show directory $pager $ftmp echo "enter line number (0 or b for back), (o)pen other, e(x)it, (q)uit!" read inp case $inp in # set action flag q*|x*) ln=0 ; act=$ACT_quit ;; o*) ln=0 ; act=$ACT_other echo "other server? (empty=same)" read inp s_ser=${inp:-$s_ser} echo "port? (empty=$gopherport)" read inp s_por=${inp:-$gopherport} echo "directory? (may be empty)" read s_dir ;; b*) ln=0 ; act=$ACT_back ;; *) ln=${inp:-0} if [ $ln = 0 ] ; then act=$ACT_back else act=$ACT_select fi ;; esac done s_act=$act case $s_act in $ACT_back|$ACT_other) s_typ=1 ;; *) s_typ=`grep "^ $ln " $dirtmp | cut -f 2 | sed -e 's/\(.\).*/\1/'` s_por=`grep "^ $ln " $dirtmp | cut -f 5` # if not enough fields, it's a top level address (server only) if [ "$s_por" = "" ] ; then s_dir=/ s_ser=`grep "^ $ln " $dirtmp | cut -f 3` s_por=`grep "^ $ln " $dirtmp | cut -f 4` # otherwise, directory is given as well else s_dir=`grep "^ $ln " $dirtmp | cut -f 3` s_ser=`grep "^ $ln " $dirtmp | cut -f 4` fi ;; esac } # save current point in stack pushlevel () { echo "$s_ser $s_por $s_dir" >>$stack } # recall point from stack poplevel () { s_ser=`tail -n 1 $stack | cut -f 1` s_por=`tail -n 1 $stack | cut -f 2` s_dir=`tail -n 1 $stack | cut -f 3` ln=`wc $stack | { read l dummy ; echo $l ; }` if [ $ln -gt 0 ] ; then ln=`expr $ln - 1` if head -n $ln $stack >$ftmp 2>/dev/null ; then cat $ftmp >$stack else :>$stack fi else echo "no more data in history, quitting" rmexit 0 fi } # main program # initialize stack with first arguments, save some "spare" rm -f $stack pushlevel s_act=X while [ $s_act != $ACT_quit ] ; do pushlevel if getdir ; then selectdir case $s_act in $ACT_back) poplevel ; poplevel ;; $ACT_other) echo "going to $s_ser : $s_por, fetching $s_dir" ;; $ACT_select) case $s_typ in 1) echo "changing to $s_dir" ;; 8) echo "telnetting..." $telnet $s_ser $s_por echo "** telnet finished, hit return to continue..." read inp poplevel ;; # otherwise download *) echo "downloading $s_dir ..." if [ "$s_typ" = "7" ] ; then echo "please enter request string:" read request s_dir="$s_dir?$request" fi if echo "$s_dir" | mync "$s_ser" "$s_por" >$ftmp then case $s_typ in 0) $pager $ftmp ;; 7) $pager $ftmp ;; g) $imgviewer $ftmp ;; h) $browser $ftmp ;; I) $imgviewer $ftmp ;; *) echo "cannot display file type $s_typ, only save" ;; esac echo "** enter local filename to save (empty: no saving)" read inp while [ "$inp" != "" ] ; do if [ -f "$inp" ] ; then echo "warning: $inp exists!" elif cat $ftmp >"$inp" ; then break else echo "error: could not write file $inp!" echo "enter local filename to save (empty: no saving)" fi read inp done else echo "cannot download $s_dir!" fi poplevel esac ;; $ACT_quit) echo "bye!" ;; *) echo "** unrecognized command, internal error! trying to go on..." poplevel ;; esac else echo "** error getting $s_dir from $s_ser:$s_por!" poplevel ; poplevel fi done rmexit 0 ::: Fri Jan 29 00:20:33 UTC 2010 ::: reply via mailto:yargo+glog@jerq.org?Subject=g100290011 -----