summaryrefslogtreecommitdiff
path: root/Misc
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-08-12 22:59:04 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-08-12 22:59:04 +0000
commit8d1b4b1358db02d6c9426e4bb3553583e11bf112 (patch)
treea3095364536d55f8356ac99559e440cc91f33eb1 /Misc
parent5714953c514a5fea35dcd819caf1afef4d92a13b (diff)
downloadzsh-8d1b4b1358db02d6c9426e4bb3553583e11bf112.tar.gz
zsh-8d1b4b1358db02d6c9426e4bb3553583e11bf112.zip
Sync up with zsh-3_1_6-pws-1.
Diffstat (limited to 'Misc')
-rw-r--r--Misc/.lastloc2
-rw-r--r--Misc/new-completion-examples453
-rw-r--r--Misc/zftp-functions1281
3 files changed, 0 insertions, 1736 deletions
diff --git a/Misc/.lastloc b/Misc/.lastloc
deleted file mode 100644
index 8ba7dd946..000000000
--- a/Misc/.lastloc
+++ /dev/null
@@ -1,2 +0,0 @@
-(("/home/user2/pws/src/zsh-3.1.5/Misc/globtests.ksh" . 2763)
- ("/home/user2/pws/src/zsh-3.1.5/Misc/globtests" . 3123))
diff --git a/Misc/new-completion-examples b/Misc/new-completion-examples
deleted file mode 100644
index 659679891..000000000
--- a/Misc/new-completion-examples
+++ /dev/null
@@ -1,453 +0,0 @@
-# Define a new widget behaving like `expand-or-complete' but calling the
-# function `main-complete' to generate matches.
-
-zle -c my-comp expand-or-complete main-complete
-
-bindkey '\C-i' my-comp
-
-
-# Below is a proposed main loop and the things it needs.
-
-# One associative array for normal completions and one for patterns.
-
-typeset -A comps
-
-
-# These may be used to define completion handlers. First argument is the
-# name of the function/variable containing the definition, the other
-# arguments are the command names for which this definition should be used.
-# With only one argument the function/variable-name __$1 is used.
-
-defcomp() {
- local v
-
- if [[ $# -eq 1 ]] then
- comps[$1]="__$1"
- else
- v="$1"
- shift
- for i; do
- comps[$i]="$v"
- done
- fi
-}
-
-defpatcomp() {
- if [[ ${+patcomps} == 1 ]] then
- patcomps=("$patcomps[@]" "$2 $1" )
- else
- patcomps=( "$2 $1" )
- fi
-}
-
-
-# These can be used to easily save and restore the state of the special
-# variables used by the completion code.
-
-alias compsave='local _opre _oipre _oargs _ocur;_opre="$PREFIX";_oipre="$IPREFIX";_oargs=( "$@" );_ocur="$CURRENT"'
-alias compreset='PREFIX="$_opre";IPREFIX="$_oipre";argv=( "$_oargs[@]" );CURRENT="$_ocur"'
-
-# This is an easy way to get completion for sub-commands.
-
-alias compsub='do-complete "$@" || return 1'
-
-# This searches $1 in the array for normal completions and calls the result.
-
-compalso() {
- 1="$comps[$1]"
- [[ -z "$1" ]] || call-complete "$@"
-}
-
-# This generates matches. The first argument is something we got from one
-# of the associative arrays above. This is expected to be either the name
-# of a variable in which case we use its value as arguments to complist,
-# or it is the name of a function in which case we call this function with
-# the arguments from the command line as its arguments.
-
-call-complete() {
- local var
-
- eval var\=\$\{\+$1\}
- if [[ "$var" == 0 ]] then
- "$@"
- else
- eval complist \$\{${1}\[\@\]\}
- fi
-}
-
-# The main loop of the competion code. This is what is called when TAB is
-# pressed. The completion code gives us the special variables and the
-# arguments from the command line are gives as positional parameters.
-
-main-complete() {
- emulate -R zsh
- local comp
- setopt localoptions nullglob rcexpandparam globdots
- unsetopt markdirs globsubst shwordsplit nounset
-
- # An entry for `--first--' is the replacement for `compctl -T'
- # The `|| return 1' is used throughout: if a function producing matches
- # returns non-zero this is interpreted as `do not try to produce more matches'
- # (this is the replacement for `compctl -t').
-
- comp="$comps[--first--]"
- [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
-
- # For arguments we use the `do-complete' function below called via the
- # convenience alias `compsub'.
-
- if [[ $CONTEXT == argument || $CONTEXT == command ]] then
- compsub
- else
- # Let's see if we have a special completion definition for the other
- # possible contexts.
-
- comp=''
-
- case $CONTEXT in
- redirect) comp="$comps[--redir--]";;
- math) comp="$comps[--math--]";;
- subscript) comp="$comps[--subscr--]";;
- value) comp="$comps[--value--]";;
- condition) comp="$comps[--cond--]";;
- esac
-
- # If not, we use default completion, if any.
-
- [[ -z "$comp" ]] && comp="$comps[--default--]"
- [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
- fi
-}
-
-# This does completion for a command (in command position and for the
-# arguments).
-
-do-complete() {
- local comp cmd1 cmd2 pat val
-
- # Completing in command position? If not we set up `cmd1' and `cmd2' as
- # two strings we have search in the completion definition arrays (e.g.
- # a path and the last path name component).
-
- if [[ $CONTEXT == command ]] then
- comp="$comps[--command--]"
- [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
- return 0
- elif [[ "$COMMAND[1]" == '=' ]] then
- eval cmd1\=$COMMAND
- cmd2="$COMMAND[2,-1]"
- elif [[ "$COMMAND" == */* ]] then
- cmd1="$COMMAND"
- cmd2="${COMMAND:t}"
- else
- cmd1="$COMMAND"
- eval cmd2=$(whence -p $COMMAND)
- fi
-
- # See if there are any matching pattern completions.
-
- for i in "$patcomps[@]"; do
- pat="${i% *}"
- val="${i#* }"
- if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]] then
- call-complete "$val" "$@" || return 1
- fi
- done
-
- # Now look up the two names in the normal completion array.
-
- comp="${comps[$cmd1]:-$comps[$cmd2]}"
-
- # And generate the matches, probably using default completion.
-
- [[ -z "$comp" ]] && comp="$comps[--default--]"
- [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
-}
-
-# Do sub-completion for pre-command modifiers.
-
-defcomp __precmd - noglob nocorrect exec command builtin
-__precmd() {
- COMMAND="$1"
- shift
- (( CURRENT-- ))
- if [[ CURRENT -eq 0 ]] then
- CONTEXT=command
- else
- CONTEXT=argument
- fi
- compsub
-}
-
-# Utility function for in-path completion.
-# First argument should be an complist-option (e.g. -f, -/, -g). The other
-# arguments should be glob patterns, one per argument.
-# E.g.: files -g '*.tex' '*.texi'
-# This is intended as a replacement for `complist -f', `complist -/', and
-# `complist -g ...' (but don't use it with other options).
-# This function behaves as if you have a matcher definition like:
-# compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,'
-# so you may want to modify this.
-
-pfiles() {
- local nm str pa pre epre a b c s rest
-
- setopt localoptions nullglob rcexpandparam globdots extendedglob
- unsetopt markdirs globsubst shwordsplit nounset
-
- nm=$NMATCHES
- if [[ $# -eq 0 ]] then
- complist -f
- elif [[ "$1" = -g ]] then
- complist -g "$argv[2,-1]"
- shift
- else
- complist $1
- shift
- fi
- [[ -nmatches nm ]] || return
-
- str="$PREFIX*$SUFFIX"
-
- [[ -z "$1" ]] && 1='*'
- if [[ $str[1] = \~ ]] then
- pre="${str%%/*}/"
- eval epre\=$pre
- str="${str#*/}"
- pa=''
- else
- pre=''
- epre=''
- if [[ $str[1] = / ]] then
- str="$str[2,-1]"
- pa='/'
- else
- pa=''
- fi
- fi
- str="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
- while [[ "$str" = */* ]] do
- rest="${str#*/}"
- a="${epre}${pa}(#l)${str%%/*}(-/)"
- a=( $~a )
- if [[ $#a -eq 0 ]] then
- return
- elif [[ $#a -gt 1 ]] then
- c=()
- s=( $rest$@ )
- s=( "${(@)s:gs.**.*.}" )
- for i in $a; do
- b=( $~i/(#l)$~s )
- eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
- [[ $#b -ne 0 ]] && c=( $c $i )
- done
- if [[ $#c -eq 0 ]] then
- return
- elif [[ $#c -ne 1 ]] then
- a="$epre$pa"
- c=( $~c/(#l)$~s )
- eval c\=\( \$\{c:/\*\(${(j:|:)fignore}\)\} \)
- c=( ${c#$a} )
- for i in $c; do
- compadd -p "$pre$pa" -W "$a" -s "/${i#*/}" -f "${i%%/*}"
- done
- return
- fi
- a=( "$c[1]" )
- fi
- a="$a[1]"
- pa="$pa${a##*/}/"
- str="$rest"
- done
- a="$epre$pa"
- s=( $str$@ )
- s=( "${(@)s:gs.**.*.}" )
- b=( $~a(#l)$~s )
- eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
- compadd -p "$pre$pa" -W "$epre$pa" -f ${b#$a}
-}
-
-# Utility function for completing files of a given type or any file.
-# In many cases you will want to call this one instead of pfiles().
-
-files() {
- local nm
-
- nm=$NMATCHES
- pfiles "$@"
-
- [[ $# -ne 0 && -nmatches nm ]] && pfiles
-}
-
-# Simple default, command, and math completion defined with variables.
-
-defcomp __default --default--
-__default() {
- files
-}
-
-defcomp __command --command--
-__command=( -c )
-
-defcomp __math --math--
-__math=( -v )
-
-defcomp __subscr --subscr--
-__subscr() {
- compalso --math-- "$@"
- # ...probably other stuff
-}
-
-# A simple pattern completion, just as an example.
-
-defpatcomp __x_options '*/X11/*'
-__x_options() {
- complist -J options -k '(-display -name -xrm)'
-}
-
-# A better example: completion for `find'.
-
-defcomp find
-__find() {
- compsave
-
- if [[ -mbetween -(ok|exec) \\\; ]] then
- compsub
- elif [[ -iprefix - ]] then
- complist -s 'daystart {max,min,}depth follow noleaf version xdev \
- {a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
- {i,}{l,}name {no,}{user,group} path perm regex size true uid used \
- exec {f,}print{f,0,} ok prune ls'
- compreset
- elif [[ -position 1 ]] then
- complist -g '. ..'
- files -g '(-/)'
- elif [[ -mcurrent -1 -((a|c|)newer|fprint(|0|f)) ]] then
- files
- elif [[ -current -1 -fstype ]] then
- complist -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)'
- elif [[ -current -1 -group ]] then
- complist -k groups
- elif [[ -current -1 -user ]] then
- complist -u
- fi
-}
-
-# Various completions...
-
-defcomp __gunzip gunzip zcat
-__gunzip() {
- files -g '*.[gG][z]'
-}
-
-defcomp gzip
-__gzip() {
- files -g '*~*.[gG][zZ]'
-}
-
-defcomp xfig
-__xfig() {
- files -g '*.fig'
-}
-
-defcomp __make make gmake
-__make() {
- complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"
-}
-
-defcomp __ps gs ghostview gview psnup psselect pswrap pstops pstruct lpr
-__ps() {
- files -g '*([pP][sS]|eps)'
-}
-
-defcomp __which which whence
-__which=( -caF )
-
-defcomp __rlogin rlogin rsh ssh
-__rlogin() {
- if [[ -position 1 ]] then
- complist -k hosts
- elif [[ -position 2 ]] then
- complist -k '(-l)'
- elif [[ -position 3 && -word 1 artus ]] then
- complist -k '(puck root)'
- fi
-}
-
-defcomp __dvi xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
-__dvi() {
- files -g '*.(dvi|DVI)'
-}
-
-defcomp __dirs rmdir df du dircmp cd
-__dirs() {
- files -/ '*(-/)'
-}
-
-defcomp __jobs fg bg jobs
-__jobs=(-j -P '%?')
-
-defcomp kill
-__kill() {
- if [[ -iprefix '-' ]] then
- complist -k signals
- else
- complist -P '%?' -j
- fi
-}
-
-defcomp __uncompress uncompress zmore
-__uncompress() {
- files -g '*.Z'
-}
-
-defcomp compress
-__compress() {
- files -g '*~*.Z'
-}
-
-defcomp __tex tex latex glatex slitex gslitex
-__tex() {
- files -g '*.(tex|TEX|texinfo|texi)'
-}
-
-defcomp __options setopt unsetopt
-__options=(-M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o)
-
-defcomp __funcs unfunction
-__funcs=(-F)
-
-defcomp __aliases unalias
-__aliases=(-a)
-
-defcomp __vars unset
-__vars=(-v)
-
-defcomp __enabled disable
-__enabled=(-FBwa)
-
-defcomp __disabled enable
-__disabled=(-dFBwa)
-
-defcomp __pdf acroread
-__pdf() {
- files -g '*.(pdf|PDF)'
-}
-
-defcomp tar
-__tar() {
- local nm tf
- compsave
-
- tf="$2"
- nm=$NMATCHES
- if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]] then
- complist -k "( $(tar tf $tf) )"
- compreset
- elif [[ -mword 1 *c*f* && -position 3 100000 ]] then
- files
- compreset
- elif [[ -mcurrent -1 *f* && -position 2 ]] then
- files -g '*.(tar|TAR)'
- fi
-}
diff --git a/Misc/zftp-functions b/Misc/zftp-functions
deleted file mode 100644
index a07e46d72..000000000
--- a/Misc/zftp-functions
+++ /dev/null
@@ -1,1281 +0,0 @@
-# zftp is a loadable module implementing an FTP client as a builtin
-# command so that you can use the shell command language and line
-# editing to make life easier. If your system has dynamically
-# load libraries and zsh was compiled to use them, it is probably
-# somewhere where it can be loaded at run time. Otherwise, it depends
-# whether the shell was compiled with zftp already built into it.
-#
-# Here is a suite of functions, plus assorted other code, to make
-# zftp work smoothly.
-#
-# Completion is implemented in a fairly natural way, except that
-# very little support has been provided for non-UNIX remote hosts.
-# On such machines, the safest thing to do is only try to complete
-# files in the current directory; this should be OK.
-#
-# Remote globbing for commands which retrieve files is also
-# implemented. This can be done in two different ways. The default
-# is for zsh to do the globbing locally. The advantage is that full
-# zsh pattern matching (respecting the setting of extendedglob) is
-# possible, and no assumption (apart from the restrictions on
-# directory handling noted above) is made about the behaviour of the
-# server. The disadvantage is that the entire filename list for the
-# current directory must be retrieved, and then zsh must laboriously
-# do pattern matching against every file, so it is potentially slow
-# for large directories. Only the non-directory part of file names is
-# globbed.
-#
-# The alternative will be used if $zfrglob has non-zero length.
-# Zsh then sends the pattern to the server for globbing. Best of
-# luck.
-#
-# To support remote globbing, some functions have been aliased
-# with 'noglob' in front. Currently, this has a dire effect on
-# completion unless the completeinaliases option is set, so
-# it is set below. This can conceivably cause you problems
-# if you expect completion for aliases automatically to give you
-# completion for the base command. I suspect that most people
-# don't even know that happens.
-#
-# The following functions are provided.
-#
-# General status changing and displaying functions:
-# zfparams
-# Simple front end to `zftp params', except it will automatically
-# query host, user and password. These are then stored to be
-# used with a `zfopen' with no arguments.
-# zfopen [ host [ user ... ] ]
-# Open a connection and login. Unless the option -1 (once)
-# is given, will store the parameters for the open (including
-# a password which is prompted for and not echoed) so that
-# if you call zfopen subsequently without arguments it will
-# reopen the same connection.
-# zfanon anonftphost
-# Open a connection for anonymous FTP. Tries to guess an
-# email address to use as the password, unless $EMAIL_ADDR is
-# already set. The first time, will tell you what it has guessed.
-# It's rude to set EMAIL_ADDR=mozilla.
-# zfcd [ dir | old new ]
-# Change directory on the server. This tries to mimic the behaviour
-# of the shell's cd. In particular,
-# zfcd change to '~' on server, if it interprets it
-# zfcd - change to previous directory of current connection
-# zfcd OLD NEW change directory from fooOLDbar to fooNEWbar
-# One piece of magic is builtin: an initial part of the directory
-# matching $HOME is translated back to `~'. Most UNIX servers
-# recognise the usual shell convention. So things like `zfcd $PWD'
-# is useful provide you are under your home directory and the
-# structure on the remote machine mirrors that on the local.
-# zfhere
-# Synonym for `zfcd $PWD', see above.
-# zfdir [args]
-# Show a long diretory list of the remote connection. Any
-# arguments are passed on to the server, apart from options.
-# Currently this always uses a pager to show the directory
-# list. Caching is implemented: zfdir on its own always shows
-# the current diretory, which is cached; zfdir with some other
-# directory arguments shows that, which is cached separately
-# and can be reviewed with `zfdir -r'. Other options:
-# -f force reget, overriding the cache, in case something's changed
-# -d delete the cache, but don't show anything.
-# To pass options to the server, use e.g. `zfdir -- -C'.
-# This also has the zfcd ~ hack.
-# zfls [args]
-# Short list of the long directory, depending on what [args]
-# do to the server. No options, no caching, no pager.
-# zftype [ a[scii] | i[mage] | b[inary] ]
-# Set or display the transfer type; currently only ASCII
-# and image (same as binary) types are supported.
-# zfclose
-# Close the connection.
-# zfstat
-# Print the zftp status from local variables; doesn't do any network
-# operations unless -v is supplied, in which case the server is
-# asked for its views on the status, too.
-#
-# Functions for retrieving data:
-# All accept the following options:
-# -G Don't do remote globbing (see above); the default is to do it.
-# -t Try to set local files to the same time as the remote ones.
-# Unfortunately we only know the remote time in GMT, so it's
-# a little tricky and you need perl 5 (installed as `perl')
-# for this to work. Suggestions welcome.
-# zfget file1 file2 ...
-# Retrieve each file from the server. The remote file is the
-# full name given, the local file is the non-directory part of that
-# (assuming UNIX file paths).
-# zfuget file1 file2 ..
-# Get with update. Check remote and local sizes and times and
-# retrieve files which are newer on the server. Will query
-# hard cases, which are where the remote file is newer but a
-# different size, or is older but the same size. With option -s
-# (silent) assumes it's best to retrieve the files in both those
-# cases. With -v (may be combined with -s), print the information
-# about the files being considered.
-# zfcget file1 ...
-# Assuming file1 was incompletely retrieved, try to get the rest of
-# it. This relies on a normal UNIX server behaviour which is not
-# as specified in the FTP standard and hence is not universal.
-# zfgcp file1 file2
-# zfgcp file1 file2 ... dir
-# Get with the behaviour of cp, i.e. copy remote file1 to local
-# file2, or get remote fileN into local diretory dir.
-#
-# Function for sending data:
-# zfput file1 file2 ...
-# Put the local files onto the server under the same name. The
-# local files are exactly as given; the remote files are the
-# non-diretory parts of that.
-# zfuput file1 file2 ..
-# Put the local files onto the server, with update. Works
-# similarly to zfuget.
-#
-# Utility functions:
-# zftp_chpwd
-# Show the new directory when it changes; try to put it into
-# an xterm on shelltool header. Works best alongside chpwd.
-# zftp_progress
-# Show the percentage of a file retrieved as it is coming; if the
-# size is not available show the size transferred so far. The
-# percentage may be wrong if sending data from a local pipe.
-# If you transfer files in the background, you should undefine
-# this before the transfer. It is smart enough not to print
-# anything when stderr is not a terminal.
-# zfcd_match
-# Function for remote directory completion.
-# zfget_match
-# Function for remote filename completion.
-# zfrglob varname
-# This is used for the remote globbing. The pattern resides
-# in $varname (note extra level of indirection), and on return
-# $varname will contain the list of matching files.
-# zfrtime locfile remfile [ time ]
-# This sad thing does the setting of local file times to those
-# of the remote, see horror story above.
-
-zmodload -ia zftp
-
-alias zfcd='noglob zfcd'
-alias zfget='noglob zfget'
-alias zfls='noglob zfls'
-alias zfdir='noglob zfdir'
-alias zfuget='noglob zfuget'
-# only way of getting that noglob out of the way at the moment
-setopt completealiases
-
-#
-# zftp completions
-#
-compctl -f -x 'p[1]' \
- -k '(open params user login type ascii binary mode put putat
- get getat append appendat ls dir local remote mkdir rmdir delete
- close quit)' - \
- 'w[1,cd][1,ls][1,dir][1,rmdir]' -K zfcd_match -S/ -q - \
- 'W[1,get*]' -K zfget_match - 'w[1,delete][1,remote]' -K zfget_match - \
- 'w[1,open][1,params]' -k hosts -- zftp
-compctl -K zfcd_match -S/ -q zfcd zfdir zfls
-compctl -K zfget_match zfget zfgcp zfuget zfcget
-compctl -k hosts zfopen zfparams
-
-function zfanon {
- local opt optlist once
-
- while [[ $1 = -* ]]; do
- if [[ $1 = - || $1 = -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $optlist[$i] in
- 1) once=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- if [[ -z $EMAIL_ADDR ]]; then
- # Exercise in futility. There's a poem by Wallace Stevens
- # called something like `N ways of looking at a blackbird',
- # where N is somewhere around 0x14 to 0x18. Now zftp is
- # ashamed to prsent `N ways of looking at a hostname'.
- local domain host
- # First, maybe we've already got it. Zen-like.
- if [[ $HOST = *.* ]]; then
- # assume this is the full host name
- host=$HOST
- elif [[ -f /etc/resolv.conf ]]; then
- # Next, maybe we've got resolv.conf.
- domain=$(awk '/domain/ { print $2 }' /etc/resolv.conf)
- [[ -n $domain ]] && host=$HOST.$domain
- fi
- # Next, maybe we've got nlsookup. May not work on LINUX.
- [[ -z $host ]] && host=$(nslookup $HOST | awk '/Name:/ { print $2 }')
- if [[ -z $host ]]; then
- # we're running out of ideas, but this should work.
- # after all, i wrote it...
- # don't want user to know about this, too embarrassed.
- local oldvb=$ZFTP_VERBOSE oldtm=$ZFTP_TMOUT
- ZFTP_VERBOSE=
- ZFTP_TMOUT=5
- if zftp open $host >& /dev/null; then
- host=$ZFTP_HOST
- zftp close $host
- fi
- ZFTP_VERBOSE=$oldvb
- ZFTP_TMOUT=$oldtm
- fi
- if [[ -z $host ]]; then
- print "Can't get your hostname. Define \$EMAIL_ADDR by hand."
- return 1;
- fi
- EMAIL_ADDR="$USER@$host"
- print "Using $EMAIL_ADDR as anonymous FTP password."
- fi
-
- if [[ $once = 1 ]]; then
- zftp open $1 anonymous $EMAIL_ADDR
- else
- zftp params $1 anonymous $EMAIL_ADDR
- zftp open
- fi
-}
-
-function zfcd {
- # zfcd: change directory on the remote server.
- #
- # Currently has the following features:
- # --- an initial string matching $HOME in the directory is turned back into ~
- # to be re-interpreted by the remote server.
- # --- zfcd with no arguments changes directory to '~'
- # --- `zfcd old new' and `zfcd -' work analagously to cd
- # --- if the connection is not currently open, it will try to
- # re-open it with the stored parameters as set by zfopen.
- # If the connection timed out, however, it won't know until
- # too late. In that case, just try the same zfcd command again
- # (but now `zfcd -' and `zfcd old new' won't work).
-
- # hack: if directory begins with $HOME, turn it back into ~
- # there are two reasons for this:
- # first, a ~ on the command line gets expanded even with noglob.
- # (I suppose this is correct, but I wouldn't like to swear to it.)
- # second, we can no do 'zfcd $PWD' and the like, and that will
- # work just as long as the directory structures under the home match.
-
- # Autoopen: if not already open, hope there are parameters set up to
- # do so. If not, we get the right error message, so no harm done.
- [[ -z $ZFTP_HOST ]] && { zfopen || return 1; }
-
- if [[ $1 = $HOME || $1 = $HOME/* ]]; then
- 1="~${1#$HOME}"
- fi
-
- if (( $# == 0 )); then
- # Emulate `cd' behaviour
- set -- '~'
- elif [[ $# -eq 1 && $1 = - ]]; then
- # Emulate `cd -' behaviour.
- set -- $zflastdir
- elif [[ $# -eq 2 ]]; then
- # Emulate `cd old new' behaviour.
- # We have to find a character not in $1 or $2; ! is a good bet.
- eval set -- "\${ZFTP_PWD:s!$1!$2!}"
- fi
-
- # We have to remember the current directory before changing it
- # if we want to keep it.
- local lastdir=$ZFTP_PWD
-
- zftp cd "$@" && zflastdir=$lastdir
-}
-
-function zfcd_match {
- # see zfcd for details of this hack
- if [[ $1 = $HOME || $1 = $HOME/* ]]; then
- 1="~${1#$HOME}"
- fi
-
- # error messages only
- local ZFTP_VERBOSE=45
- # should we redirect 2>/dev/null or let the user see it?
-
- if [[ $ZFTP_SYSTEM = UNIX* ]]; then
- # hoo, aren't we lucky: this makes things so much easier
- setopt localoptions rcexpandparam
- local dir
- if [[ $1 = ?*/* ]]; then
- dir=${1%/*}
- elif [[ $1 = /* ]]; then
- dir=/
- fi
- # If we're using -F, we get away with using a directory
- # to list, but not a glob. Don't ask me why.
- # I hate having to rely on awk here.
- reply=($(zftp ls -F $dir |
- awk '/\/$/ { print substr($1, 0, length($1)-1) }'))
- if [[ $dir = / ]]; then
- reply=(${dir}$reply)
- elif [[ -n $dir ]]; then
- reply=($dir/$reply)
- fi
- else
- # I simply don't know what to do here.
- # Just use the list of files for the current directory.
- zfget_match $*
- fi
-
-}
-
-function zfcget {
- # Continuation get of files from remote server.
- # For each file, if it's shorter here, try to get the remainder from
- # over there. This requires the server to support the REST command
- # in the way many do but RFC959 doesn't specify.
- # Options:
- # -G don't to remote globbing, else do
- # -t update the local file times to the same time as the remote.
- # Currently this only works if you have the `perl' command,
- # and that perl is version 5 with the standard library.
- # See the function zfrtime for more gory details.
-
- setopt localoptions
- unsetopt ksharrays shwordsplit
-
- local loc rem stat=0 optlist opt nglob remlist locst remst
- local tmpfile=${TMPPREFIX}zfcget$$ rstat tsize time
-
- while [[ $1 = -* ]]; do
- if [[ $1 = - || $1 = -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $optlist[$i] in
- G) nglob=1
- ;;
- t) time=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- for remlist in $*; do
- # zfcd directory hack to put the front back to ~
- if [[ $remlist = $HOME || $remlist = $HOME/* ]]; then
- remlist="~${remlist#$HOME}"
- fi
- if [[ $nglob != 1 ]]; then
- zfrglob remlist
- fi
- if (( $#remlist )); then
- for rem in $remlist; do
- loc=${rem:t}
- if [[ ! -f $loc ]]; then
- # File does not yet exist
- zftp get $rem >$loc || stat=$?
- else
- # Compare the sizes.
- locst=($(zftp local $loc))
- zftp remote $rem >$tmpfile
- rstat=$?
- remst=($(<$tmpfile))
- rm -f $tmpfile
- if [[ $rstat = 2 ]]; then
- print "Server does not support SIZE command.\n" \
- "Assuming you know what you're doing..." 2>&1
- zftp getat $rem $locst[1] >>$loc || stat=$?
- continue
- elif [[ $rstat = 1 ]]; then
- print "Remote file not found: $rem" 2>&1
- continue
- fi
- if [[ $locst[1] -gt $remst[1] ]]; then
- print "Local file is larger!" 2>&1
- continue;
- elif [[ $locst[1] == $remst[1] ]]; then
- print "Files are already the same size." 2>&1
- continue
- else
- if zftp getat $rem $locst[1] >>$loc; then
- [[ $time = 1 ]] && zfrtime $loc $rem $remst[2]
- else
- stat=1
- fi
- fi
- fi
- done
- fi
- done
-
- return $stat
-}
-
-function zfclose {
- zftp close
-}
-
-function zfdir {
- # Long directory of remote server.
- # The remote directory is cached. In fact, two caches are kept:
- # one of the standard listing of the current directory, i.e. zfdir
- # with no arguments, and another for everything else.
- # To access the appropriate cache, just use zfdir with the same
- # arguments as previously. zfdir -r will also re-use the `everything
- # else' cache; you can always reuse the current directory cache just
- # with zfdir on its own.
- #
- # The current directory cache is emptied when the directory changes;
- # the other is kept until a new zfdir with a non-empty argument list.
- # Both are removed when the connection is closed.
- #
- # zfdir -f will force the existing cache to be ignored, e.g. if you know
- # or suspect the directory has changed.
- # zfdir -d will remove both caches without listing anything.
- # If you need to pass -r, -f or -d to the dir itself, use zfdir -- -d etc.
-
- setopt localoptions unset
- unsetopt shwordsplit ksharrays
-
- local file opt optlist redir i newargs force
-
- while [[ $1 = -* ]]; do
- if [[ $1 = - || $1 = -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $optlist[$i] in
- r) redir=1
- ;;
- f) force=1
- ;;
- d) [[ -n $zfcurdir && -f $zfcurdir ]] && rm -f $zfcurdir
- [[ -n $zfotherdir && -f $zfotherdir ]] && rm -f $zfotherdir
- zftp_fcache=()
- return 0
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- # directory hack, see zfcd
- for (( i = 1; i <= $#argv; i++ )); do
- if [[ $argv[$i] = $HOME || $argv[$i] = $HOME/* ]]; then
- argv[$i]="~${argv[$i]#$HOME}"
- fi
- done
-
- if [[ $# -eq 0 ]]; then
- # Cache it in the current directory file. This means that repeated
- # calls to zfdir with no arguments always use a cached file.
- [[ -z $zfcurdir ]] && zfcurdir=${TMPPREFIX}zfcurdir$$
- file=$zfcurdir
- else
- # Last directly looked at was not the current one, or at least
- # had non-standard arguments.
- [[ -z $zfotherdir ]] && zfotherdir=${TMPPREFIX}zfotherdir$$
- file=$zfotherdir
- newargs="$*"
- if [[ -f $file && $redir != 1 && $force -ne 1 ]]; then
- # Don't use the cached file if the arguments changed.
- [[ $newargs = $zfotherargs ]] || rm -f $file
- fi
- zfotherargs=$newargs
- fi
-
- if [[ $force -eq 1 ]]; then
- rm -f $file
- # if it looks like current directory has changed, better invalidate
- # the filename cache, too.
- (( $# == 0 )) && zftp_fcache=()
- fi
-
- if [[ -n $file && -f $file ]]; then
- eval ${PAGER:-more} \$file
- else
- zftp dir $* | tee $file | eval ${PAGER-:more}
- fi
-}
-
-function zfgcp {
- # ZFTP get as copy: i.e. first arguments are remote, last is local.
- # Supposed to work exactly like a normal copy otherwise, i.e.
- # zfcp rfile lfile
- # or
- # zfcp rfile1 rfile2 rfile3 ... ldir
- # Options:
- # -G don't to remote globbing, else do
- # -t update the local file times to the same time as the remote.
- # Currently this only works if you have the `perl' command,
- # and that perl is version 5 with the standard library.
- # See the function zfrtime for more gory details.
-
- setopt localoptions
- unsetopt shwordsplit
-
- local opt optlist nglob remlist rem loc stat=0 time
-
- while [[ $1 == -* ]]; do
- if [[ $1 == - || $1 == -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $opt in
- G) nglob=1
- ;;
- t) time=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- # hmm, we should really check this after expanding the glob,
- # but we shouldn't expand the last argument remotely anyway.
- if [[ $# -gt 2 && ! -d $argv[-1] ]]; then
- print "zfgcp: last argument must be a directory." 2>&1
- return 1
- elif [[ $# == 1 ]]; then
- print "zfgcp: not enough arguments." 2>&1
- return 1
- fi
-
- if [[ -d $argv[-1] ]]; then
- local dir=$argv[-1]
- argv[-1]=
- for remlist in $*; do
- # zfcd directory hack to put the front back to ~
- if [[ $remlist = $HOME || $remlist = $HOME/* ]]; then
- remlist="~${remlist#$HOME}"
- fi
- if [[ $nglob != 1 ]]; then
- zfrglob remlist
- fi
- if (( $#remlist )); then
- for rem in $remlist; do
- loc=$dir/${rem:t}
- if zftp get $rem >$loc; then
- [[ $time = 1 ]] && zfrtime $rem $loc
- else
- stat=1
- fi
- done
- fi
- done
- else
- zftp get $1 >$2 || stat=$?
- fi
- return $stat
-}
-
-function zfget {
- # Get files from remote server. Options:
- # -G don't to remote globbing, else do
- # -t update the local file times to the same time as the remote.
- # Currently this only works if you have the `perl' command,
- # and that perl is version 5 with the standard library.
- # See the function zfrtime for more gory details.
-
- local loc rem stat=0 optlist opt nglob remlist time
-
- while [[ $1 == -* ]]; do
- if [[ $1 == - || $1 == -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $opt in
- G) nglob=1
- ;;
- t) time=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- for remlist in $*; do
- # zfcd directory hack to put the front back to ~
- if [[ $remlist == $HOME || $remlist == $HOME/* ]]; then
- remlist="~${remlist#$HOME}"
- fi
- if [[ $nglob != 1 ]]; then
- zfrglob remlist
- fi
- if (( $#remlist )); then
- for rem in $remlist; do
- loc=${rem:t}
- if zftp get $rem >$loc; then
- [[ $time = 1 ]] && zfrtime $rem $loc
- else
- stat=1
- fi
- done
- fi
- done
-
- return $stat
-}
-
-function zfget_match {
- # the zfcd hack: this may not be necessary here
- if [[ $1 == $HOME || $1 == $HOME/* ]]; then
- 1="~${1#$HOME}"
- fi
-
-
- if [[ $ZFTP_SYSTEM == UNIX* && $1 == */* ]]; then
- # On the first argument to ls, we usually get away with a glob.
- reply=($(zftp ls "$1*$2"))
- else
- if (( $#zftp_fcache == 0 )); then
- # Always cache the current directory and use it
- # even if the system is UNIX.
- zftp_fcache=($(zftp ls))
- fi
- reply=($zftp_fcache);
- fi
-}
-
-function zfhere {
- # Change to the directory corresponding to $PWD on the server.
- # See zfcd for how this works.
- zfcd $PWD
-}
-
-function zfls {
- # directory hack, see zfcd
- if [[ $1 = $HOME || $1 = $HOME/* ]]; then
- 1="~${1#$HOME}"
- fi
- zftp ls $*
-}
-
-function zfopen {
- # Use zftp params to set parameters for open, rather than sending
- # them straight to open. That way they are stored for a future open
- # command.
- #
- # With option -1 (just this 1ce), don't do that.
-
- local optlist opt once
-
- while [[ $1 = -* ]]; do
- if [[ $1 = - || $1 = -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $optlist[$i] in
- 1) once=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- # This is where we should try and do same name-lookupage in
- # both .netrc and .ncftp/bookmarks . We could even try saving
- # the info in their for new hosts, like ncftp does.
-
- if [[ $once = 1 ]]; then
- zftp open $*
- else
- # set parameters, but only if there was at least a host
- (( $# > 0 )) && zfparams $*
- # now call with no parameters
- zftp open
- fi
-}
-
-function zfparams {
- # Set to prompt for any user or password if not given.
- # Don't worry about accounts here.
- if (( $# > 0 )); then
- (( $# < 2 )) && 2='?'
- (( $# < 3 )) && 3='?'
- fi
- zftp params $*
-}
-
-function zfput {
- # Simple put: dump every file under the same name, but stripping
- # off any directory parts.
- local loc rem stat=0
- for loc in $*; do
- rem=${loc:t}
- zftp put $rem <$loc
- [[ $? == 0 ]] || stat=$?
- done
- return $stat
-}
-
-function zfrglob {
- # Do the remote globbing for zfput, etc.
- # We have two choices:
- # (1) Get the entire file list and match it one by one
- # locally against the pattern.
- # Causes problems if we are globbing directories (rare, presumably).
- # But: we can cache the current directory, which
- # we need for completion anyway. Works on any OS if you
- # stick with a single directory. This is the default.
- # (2) Use remote globbing, i.e. pass it to ls at the site.
- # Faster, but only works with UNIX, and only basic globbing.
- # We do this if $zfrglob is non-null.
-
- # There is only one argument, the variable containing the
- # pattern to be globbed. We set this back to an array containing
- # all the matches.
- setopt localoptions unset
- unsetopt ksharrays
-
- local pat dir nondir files i
-
- eval pat=\$$1
-
- # Check if we really need to do anything. Look for standard
- # globbing characters, and if extendedglob is set and we are
- # using zsh for the actual pattern matching also look for
- # extendedglob characters.
- if [[ $remlist != *[][*?]* &&
- ( -n $zfrglob || ! -o extendedglob || $remlist != *[(|)~#^]* ) ]]; then
- return 0
- fi
-
- if [[ $zfrglob != '' ]]; then
- eval "$1=(\$(zftp ls \"$pat\" 2>/dev/null))"
- else
- if [[ $ZFTP_SYSTEM = UNIX* && $pat = */* ]]; then
- # not the current directory and we know how to handle paths
- if [[ $pat = ?*/* ]]; then
- # careful not to remove too many slashes
- dir=${pat%/*}
- else
- dir=/
- fi
- nondir=${pat##*/}
- files=($(zftp ls "$dir" 2>/dev/null))
- else
- # we just have to do an ls and hope that's right
- nondir=$pat
- if (( $#zftp_fcache == 0 )); then
- zftp_fcache=($(zftp ls))
- fi
- files=($zftp_fcache)
- fi
- # now we want to see which of the $files match $nondir
- for (( i = 1; i <= $#files; i++)); do
- # empty words are elided in array assignment
- [[ $files[$i] = ${~nondir} ]] || files[$i]=''
- done
- eval "$1=(\$files)"
- fi
-}
-
-function zfrtime {
- # Set the modification time of file LOCAL to that of REMOTE.
- # If the optional TIME is passed, it should be in the FTP format
- # CCYYMMDDhhmmSS, i.e. no dot before the seconds, and in GMT.
- # This is what both `zftp remote' and `zftp local' return.
- #
- # Unfortunately, since the time returned from FTP is GMT and
- # your file needs to be set in local time, we need to do some
- # hacking around with time. At the moment this requires perl 5
- # with the standard library.
-
- setopt localoptions unset
- unsetopt ksharrays
-
- local time gmtime loctime
-
- if [[ -n $3 ]]; then
- time=$3
- else
- time=($(zftp remote $2 2>/dev/null))
- [[ -n $time ]] && time=$time[2]
- fi
- [[ -z $time ]] && return 1
-
- # Now's the real *!@**!?!. We have the date in GMT and want to turn
- # it into local time for touch to handle. It's just too nasty
- # to handle in zsh; do it in perl.
- if perl -mTime::Local -e '($file, $t) = @ARGV;
- $yr = substr($t, 0, 4) - 1900;
- $mon = substr($t, 4, 2) - 1;
- $mday = substr($t, 6, 2) + 0;
- $hr = substr($t, 8, 2) + 0;
- $min = substr($t, 10, 2) + 0;
- $sec = substr($t, 12, 2) + 0;
- $time = Time::Local::timegm($sec, $min, $hr, $mday, $mon, $yr);
- utime $time, $time, $file and return 0;' $1 $time 2>/dev/null; then
- print "Setting time for $1 failed. Need perl 5." 2>1
- fi
-
- # If it wasn't for the GMT/local time thing, it would be this simple.
- #
- # time="${time[1,12]}.${time[13,14]}"
- #
- # touch -t $time $1
-
-}
-
-function zfstat {
- # Give a zftp status report using local variables.
- # With option -v, connect the remote host and ask it what it
- # thinks the status is.
-
- setopt localoptions unset
- unsetopt ksharrays
-
- local i stat=0 opt optlist verbose
-
- while [[ $1 = -* ]]; do
- if [[ $1 = - || $1 = -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $opt in
- v) verbose=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- # hack: in case the status from a subshell process hasn't been
- # fixed yet
- zftp type >&/dev/null
-
- if [[ -n $ZFTP_HOST ]]; then
- print "Host:\t\t$ZFTP_HOST"
- print "IP:\t\t$ZFTP_IP"
- [[ -n $ZFTP_SYSTEM ]] && print "System type:\t$ZFTP_SYSTEM"
- if [[ -n $ZFTP_USER ]]; then
- print "User:\t\t$ZFTP_USER "
- [[ -n $ZFTP_ACCOUNT ]] && print "Account:\t$AFTP_ACCOUNT"
- print "Directory:\t$ZFTP_PWD"
- print -n "Transfer type:\t"
- if [[ $ZFTP_TYPE = "I" ]]; then
- print Image
- elif [[ $ZFTP_TYPE = "A" ]]; then
- print Ascii
- else
- print Unknown
- fi
- print -n "Transfer mode:\t"
- if [[ $ZFTP_MODE = "S" ]]; then
- print Stream
- elif [[ $ZFTP_MODE = "B" ]]; then
- print Block
- else
- print Unknown
- fi
- else
- print "No user logged in."
- fi
- else
- print "Not connected."
- stat=1
- fi
-
- # things which may be set even if not connected:
- [[ -n $ZFTP_REPLY ]] && print "Last reply:\t$ZFTP_REPLY"
- print "Verbosity:\t$ZFTP_VERBOSE"
- print -n "Preferences:\t"
- for (( i = 1; i <= ${#ZFTP_PREFS}; i++ )); do
- case $ZFTP_PREFS[$i] in
- [pP]) print -n "Passive "
- ;;
- [sS]) print -n "Sendport "
- ;;
- [dD]) print -n "Dumb "
- ;;
- *) print -n "$ZFTP_PREFS[$i]???"
- esac
- done
- print
-
- if [[ -n $ZFTP_HOST && $verbose = 1 ]]; then
- print "Status of remote server:"
- # make sure we print the reply
- local ZFTP_VERBOSE=045
- zftp quote STAT
- fi
-
- return $stat
-}
-
-function zftp_chpwd {
- # You may want to alter chpwd to call this when $ZFTP_USER is set.
- # If so, call it with a non-zero first argument so it doesn't
- # print the new FTP directory.
-
- # Cancel the filename cache for the current directory.
- zftp_fcache=()
- # ...and also empty the stored directory listing cache.
- # As this function is called when we close the connection, this
- # is the only place we need to do these two things.
- [[ -n $zfcurdir && -f $zfcurdir ]] && rm -f $zfcurdir
-
- if [[ -z $ZFTP_USER ]]; then
- # last call, after an FTP logout
-
- # delete the non-current cached directory
- [[ -n $zfotherdir && -f $zfotherdir ]] && rm -f $zfotherdir
- zfotherargs=
-
- # don't keep zflastdir between opens
- zflastdir=
-
- # return the display to standard
- # uncomment the following line if you have a chpwd which shows directories
- # chpwd
- else
- [[ -z $zflastdir ]] && zflastdir=$ZFTP_PWD
- local args
- if [[ -t 1 && -t 2 ]]; then
- local str="$ZFTP_HOST:$ZFTP_PWD"
- [[ -z $1 ]] && print $str
- [[ ${#str} -lt 70 ]] && str="%m: %~ $str"
- case $TERM in
- sun-cmd) print -n -P "\033]l$str\033\\"
- ;;
- xterm) print -n -P "\033]2;$str\a"
- ;;
- esac
- fi
- fi
-}
-
-function zftp_progress {
- # Basic progress metre, showing the percent of the file transferred.
- # You want growing bars? You gotta write growing bars.
-
- # Don't show progress unless stderr is a terminal
- [[ ! -t 2 ]] && return 0
-
- if [[ $ZFTP_TRANSFER = *F ]]; then
- print 1>&2
- elif [[ -n $ZFTP_TRANSFER ]]; then
- if [[ -n $ZFTP_SIZE ]]; then
- local frac="$(( ZFTP_COUNT * 100 / ZFTP_SIZE ))%"
- print -n "\r$ZFTP_FILE ($ZFTP_SIZE bytes): $ZFTP_TRANSFER $frac" 1>&2
- else
- print -n "\r$ZFTP_FILE: $ZFTP_TRANSFER $ZFTP_COUNT" 1>&2
- fi
- fi
-}
-
-function zftype {
- local type
-
- if (( $# == 0 )); then
- type=$(zftp type)
- if [[ $type = I ]]; then
- print "Current type is image (binary)"
- return 0
- elif [[ $type = A ]]; then
- print "Current type is ASCII"
- return 0
- else
- return 1
- fi
- else
- if [[ $1 == [aA]([sS][cC]([iI][iI]|)|) ]]; then
- type=A
- elif [[ $1 == [iI]([mM]([aA][gG][eE]|)|) ||
- $1 == [bB]([iI][nN]([aA][rR][yY]|)|) ]]; then
- type=I
- else
- print "Type not recognised: $1" 2>&1
- return 1
- fi
- zftp type $type
- fi
-}
-
-function zfuget {
- # Get a list of files from the server with update.
- # In other words, only retrieve files which are newer than local
- # ones. This depends on the clocks being adjusted correctly
- # (i.e. if one is fifteen minutes out, for the next fifteen minutes
- # updates may not be correctly calculated). However, difficult
- # cases --- where the files are the same size, but the remote is newer,
- # or have different sizes, but the local is newer -- are prompted for.
- #
- # Files are globbed on the remote host --- assuming, of course, they
- # haven't already been globbed local, so use 'noglob' e.g. as
- # `alias zfuget="noglob zfuget"'.
- #
- # Options:
- # -G Glob: turn off globbing
- # -v verbose: print more about the files listed.
- # -s silent: don't ask, just guess. The guesses are:
- # - if the files have different sizes but remote is older ) grab
- # - if they have the same size but remote is newer )
- # which is safe if the remote files are always the right ones.
- # -t time: update the local file times to the same time as the remote.
- # Currently this only works if you have the `perl' command,
- # and that perl is version 5 with the standard library.
- # See the function zfrtime for more gory details.
-
- setopt localoptions
- unsetopt ksharrays shwordsplit
-
- local loc rem stat=0 locstats remstats doit tmpfile=${TMPPREFIX}zfuget$$
- local rstat remlist verbose optlist opt bad i silent nglob time
-
- zfuget_print_time() {
- local tim=$1
- print -n "$tim[1,4]/$tim[5,6]/$tim[7,8] $tim[9,10]:$tim[11,12].$tim[13,14]"
- print -n GMT
- }
-
- zfuget_print () {
- print -n "\nremote $rem ("
- zfuget_print_time $remstats[2]
- print -n ", $remstats[1] bytes)\nlocal $loc ("
- zfuget_print_time $locstats[2]
- print ", $locstats[1] bytes)"
- }
-
- while [[ $1 = -* ]]; do
- if [[ $1 = - || $1 = -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $optlist[$i] in
- v) verbose=1
- ;;
- s) silent=1
- ;;
- G) nglob=1
- ;;
- t) time=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- [[ -n $bad ]] && return 1
-
- for remlist in $*; do
- # zfcd directory hack to put the front back to ~
- if [[ $remlist == $HOME || $remlist == $HOME/* ]]; then
- remlist="~${remlist#$HOME}"
- fi
- if [[ $nglob != 1 ]]; then
- zfrglob remlist
- fi
- if (( $#remlist )); then
- for rem in $remlist; do
- loc=${rem:t}
- doit=y
- remstats=()
- if [[ -f $loc ]]; then
- zftp local $loc >$tmpfile
- locstats=($(<$tmpfile))
- zftp remote $rem >$tmpfile
- rstat=$?
- remstats=($(<$tmpfile))
- rm -f $tmpfile
- if [[ $rstat = 2 ]]; then
- print "Server does not implement full command set required." 1>&2
- return 1
- elif [[ $rstat = 1 ]]; then
- print "File not found on server: $rem" 1>&2
- stat=1
- continue
- fi
- [[ $verbose = 1 ]] && zfuget_print
- if (( $locstats[1] != $remstats[1] )); then
- # Files have different sizes
- if [[ $locstats[2] > $remstats[2] && $silent != 1 ]]; then
- [[ $verbose != 1 ]] && zfuget_print
- print "Local file $loc more recent than remote," 1>&2
- print -n "but sizes are different. Transfer anyway [y/n]? " 1>&2
- read -q doit
- fi
- else
- # Files have same size
- if [[ $locstats[2] < $remstats[2] ]]; then
- if [[ $silent != 1 ]]; then
- [[ $verbose != 1 ]] && zfuget_print
- print "Local file $loc has same size as remote," 1>&2
- print -n "but local file is older. Transfer anyway [y/n]? " 1>&2
- read -q doit
- fi
- else
- # presumably same file, so don't get it.
- [[ $verbose = 1 ]] && print Not transferring
- doit=n
- fi
- fi
- else
- [[ $verbose = 1 ]] && print New file $loc
- fi
- if [[ $doit = y ]]; then
- if zftp get $rem >$loc; then
- if [[ $time = 1 ]]; then
- # if $remstats is set, it's second element is the remote time
- zfrtime $loc $rem $remstats[2]
- fi
- else
- stat=$?
- fi
-
- fi
- done
- fi
- done
- return $stat
-}
-
-function zfuput {
- # Put a list of files from the server with update.
- # See zfuget for details.
- #
- # Options:
- # -v verbose: print more about the files listed.
- # -s silent: don't ask, just guess. The guesses are:
- # - if the files have different sizes but remote is older ) grab
- # - if they have the same size but remote is newer )
- # which is safe if the remote files are always the right ones.
-
- setopt localoptions
- unsetopt ksharrays shwordsplit
-
- local loc rem stat=0 locstats remstats doit tmpfile=${TMPPREFIX}zfuput$$
- local rstat verbose optlist opt bad i silent
-
- zfuput_print_time() {
- local tim=$1
- print -n "$tim[1,4]/$tim[5,6]/$tim[7,8] $tim[9,10]:$tim[11,12].$tim[13,14]"
- print -n GMT
- }
-
- zfuput_print () {
- print -n "\nremote $rem ("
- zfuput_print_time $remstats[2]
- print -n ", $remstats[1] bytes)\nlocal $loc ("
- zfuput_print_time $locstats[2]
- print ", $locstats[1] bytes)"
- }
-
- while [[ $1 = -* ]]; do
- if [[ $1 = - || $1 = -- ]]; then
- shift;
- break;
- fi
- optlist=${1#-}
- for (( i = 1; i <= $#optlist; i++)); do
- opt=$optlist[$i]
- case $optlist[$i] in
- v) verbose=1
- ;;
- s) silent=1
- ;;
- *) print option $opt not recognised >&2
- ;;
- esac
- done
- shift
- done
-
- [[ -n $bad ]] && return 1
-
- if [[ $ZFTP_VERBOSE = *5* ]]; then
- # should we turn it off locally?
- print "Messages with code 550 are harmless." >&2
- fi
-
- for loc in $*; do
- rem=${loc:t}
- doit=y
- remstats=()
- if [[ ! -f $loc ]]; then
- print "$loc: file not found" >&2
- stat=1
- continue
- fi
- zftp local $loc >$tmpfile
- locstats=($(<$tmpfile))
- zftp remote $rem >$tmpfile
- rstat=$?
- remstats=($(<$tmpfile))
- rm -f $tmpfile
- if [[ $rstat = 2 ]]; then
- print "Server does not implement full command set required." 1>&2
- return 1
- elif [[ $rstat = 1 ]]; then
- [[ $verbose = 1 ]] && print New file $loc
- else
- [[ $verbose = 1 ]] && zfuput_print
- if (( $locstats[1] != $remstats[1] )); then
- # Files have different sizes
- if [[ $locstats[2] < $remstats[2] && $silent != 1 ]]; then
- [[ $verbose != 1 ]] && zfuput_print
- print "Remote file $rem more recent than local," 1>&2
- print -n "but sizes are different. Transfer anyway [y/n]? " 1>&2
- read -q doit
- fi
- else
- # Files have same size
- if [[ $locstats[2] > $remstats[2] ]]; then
- if [[ $silent != 1 ]]; then
- [[ $verbose != 1 ]] && zfuput_print
- print "Remote file $rem has same size as local," 1>&2
- print -n "but remote file is older. Transfer anyway [y/n]? " 1>&2
- read -q doit
- fi
- else
- # presumably same file, so don't get it.
- [[ $verbose = 1 ]] && print Not transferring
- doit=n
- fi
- fi
- fi
- if [[ $doit = y ]]; then
- zftp put $rem <$loc || stat=$?
- fi
- done
- return $stat
-}