summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2017-08-25 15:20:10 +0200
committerOliver Kiddle <opk@zsh.org>2017-08-25 15:20:10 +0200
commit3fbb80b1d3581066f423e8240587cbc3f750861a (patch)
tree88fb8e14e6365ee8b9ec5c85de3f8618d14b85a0
parent93ce12e7a00208f2552a9b06248a4839b082ad56 (diff)
downloadzsh-3fbb80b1d3581066f423e8240587cbc3f750861a.tar.gz
zsh-3fbb80b1d3581066f423e8240587cbc3f750861a.tar.xz
zsh-3fbb80b1d3581066f423e8240587cbc3f750861a.zip
41601: handle system differences in arp completion and add function for route
-rw-r--r--ChangeLog4
-rw-r--r--Completion/Unix/Command/_arp110
-rw-r--r--Completion/Unix/Command/_route254
3 files changed, 353 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index ed463e905..377b390a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2017-08-25  Oliver Kiddle  <opk@zsh.org>
 
+	* 41601: Completion/Unix/Command/_arp,
+	Completion/Unix/Command/_route: handle system differences
+	in arp completion and add function for route
+
 	* 41600: Completion/Unix/Command/_mpc: fix quoting of
 	songs for completion and avoid sending errors to stderr
 
diff --git a/Completion/Unix/Command/_arp b/Completion/Unix/Command/_arp
index f340e979e..80e829022 100644
--- a/Completion/Unix/Command/_arp
+++ b/Completion/Unix/Command/_arp
@@ -1,23 +1,103 @@
 #compdef arp
 
 local state line expl curcontext="$curcontext" ret=1
-local -a cmds
+typeset -A opt_args
+local -a cmds args
 
-cmds=(-a --display -d --delete -s --set -f --file)
+flags=( temp pub )
+cmds=(
+  '(2 3)-a[show entries for all hosts]'
+  '(2 -d)-d[delete entry from table]'
+  '(-n -v)-s[create an arp entry]'
+  '(2 3 -n -v)-f[read multiple entries from file]'
+)
+args=( '-n[show numeric addresses]' )
+vopt='-v[be verbose]'
 
-_arguments -C \
-  "($cmds 1 -D --use-device)"{-a,--display}'[show entries for all or specified hosts]:host:->hostintable' \
-  "($cmds 1 -n --numeric -D --use-device -H --hw-type)"{-d,--delete}'[delete entry from table]:host:->hostintable' \
-  "($cmds 1 -n --numeric)"{-s,--set}'[create an ARP entry]:host:_hosts:ethernet address::*:option:(temp trail pub)' \
-  "($cmds 1 -n --numeric)"{-f,--file}'[read multiple entries from file]:file:_files' \
-  '(-i --device)'{-i,--device}'[select an interface]:::_net_interfaces:' \
-  '(-D --use-device -a --display -d --delete)'{-D,--use-device}"[use the interface ifa's hardware address]" \
-  '(-H --hw-type -d --delete)'{-H,--hw-type}'[class of entries to check for]:class:(ether arcnet pronet ax25 netrom)' \
-  '(-n --numeric -d --delete -s --set -f --file)'{-n,--numeric}'[shows numerical addresses]' \
-  '(-v --verbose)'{-v,--verbose}'[be verbose]' \
-  '(-a)1:host:->hostintable' && ret=0
+if (( ${+words[(r)-d]} )) && [[ $OSTYPE = (*bsd|dragonfly|darwin)* ]]; then
+  args+=( '(1 *)-a[delete all entries]' )
+fi
 
-[[ "$state" = hostintable ]] &&
-  _wanted hosts expl 'host' compadd ${${${(f)"$(${words[1]} -an)"}##[ ?(]#}%%[ )]*} && ret=0
+case $OSTYPE in
+  linux*)
+    cmds=(
+      '(2 * -D --use-device)-a[show entries in BSD style output format]'
+      '!(2 * -D --use-device)-e'
+      '(2 -n --numeric -D --use-device -H --hw-type)'{-d,--delete}'[delete entry from table]'
+      '(-n --numeric)'{-s,--set}'[create an ARP entry]'
+      '(2 * -D --use-device)'{-f,--file}'[read multiple entries from file]'
+    )
+    args=(
+      '(-i --device)'{-i+,--device=}'[select an interface]:interface:_net_interfaces'
+      '(-D --use-device -a --display -d --delete)'{-D,--use-device}"[use specified interface's hardware address]"
+      '(-H --hw-type -d --delete)'{-H+,--hw-type=}'[specify class of entries to check for]:class:(ash ether arcnet pronet ax25 netrom rose dlci fddi hippi irda x25 infiniband eui64)'
+      '(* -n --numeric -d --delete -s --set -f --file)'{-n,--numeric}'[show numeric addresses]'
+      '(-v --verbose)'{-v,--verbose}'[be verbose]'
+    )
+    flags+=( netmask )
+  ;;
+  darwin*|freebsd*|dragonfly*)
+    cmds+=( '(-n -v -i)-S[create an arp entry, replacing any existing entry]' )
+  ;|
+  darwin*|freebsd*)
+    args+=( '(-s -Q -f)-i+[select an interface]:interface:_net_interfaces' )
+  ;|
+  darwin*)
+    args+=(
+      '(-d -s -S -f)-l[show link-layer reachability information]'
+      '(-d -s -S -f)-x[show extended link-layer reachability information]'
+    )
+    flags+=( reject blackhole only ifscope )
+  ;;
+  dragonfly*)
+    flags+=( only )
+    args+=( '-c:cpu' )
+  ;;
+  netbsd*)
+    flags+=( proxy )
+    args+=( $vopt )
+  ;;
+  freebsd*)
+    args+=( $vopt )
+    flags+=( blackhole reject )
+  ;;
+  openbsd*)
+    args+=(
+      '(-a -d -W)-F[overwrite existing entries]'
+      '(-W)-V+[select the routing domain]:routing domain'
+    )
+    cmds+=(
+      '(- 1)-W[send the wake on LAN frame]'
+    )
+    flags+=( permanent )
+  ;;
+  solaris*) flags+=( trail permanent) ;;
+esac
+
+_arguments -C -s -S $args \
+  '1: :->hostintable' \
+  '2:ethernet address' \
+  "*: :->flags" \
+  + '(cmds)' $cmds && ret=0
+
+if [[ "$state" = hostintable ]]; then
+  if [[ -n $opt_args[(i)-(D|-use-device)] ]]; then
+    _wanted interfaces expl interface _net_interfaces && ret=0
+  elif [[ -n $opt_args[(i)-(f|-file)] ]]; then
+    _files && ret=0
+  elif [[ -n $opt_args[(i)-(s|S|-set)] ]]; then
+    _hosts && ret=0
+  else
+    _wanted hosts expl 'host' compadd ${${${(f)"$(${words[1]} -an)"}##[ ?(]#}%%[ )]*} && ret=0
+  fi
+elif [[ "$state" = flags ]]; then
+  if [[ $words[CURRENT-1] = netmask ]]; then
+    _message -e netmasks netmask
+  elif (( $+opt_args[-W] )) || [[ $words[CURRENT-1] = ifscope ]]; then
+    _wanted interfaces expl interface _net_interfaces && ret=0
+  else
+    _wanted flags expl flag compadd -F line $flags && ret=0
+  fi
+fi
 
 return ret
diff --git a/Completion/Unix/Command/_route b/Completion/Unix/Command/_route
new file mode 100644
index 000000000..f8426874c
--- /dev/null
+++ b/Completion/Unix/Command/_route
@@ -0,0 +1,254 @@
+#compdef route
+
+local curcontext="$curcontext" expect ret=1
+local -a state state_descr line args families modifiers ignore sub sequential tags
+local -A opt_args subcmds once params
+
+subcmds=(
+  add     'add a route'
+  flush   'remove all routes'
+  delete  'delete a specific route'
+  change  'change aspects of a route (such as its gateway)'
+  get     'lookup route for a destination'
+  monitor 'continuously report any changes to the routing information'
+)
+args=(
+  '-n[output addresses numerically]'
+  '(-q)-v[verbose output]'
+)
+modifiers=(
+  '-net:interpret destination as a network'
+  '-host:interpret destination as a host'
+)
+params=(
+  '-dst'          target  # does this definitely follow
+  '(-|)netmask'   netmask
+  '(gw|-gateway)' gateway
+  metric          metric
+  '(mss|window|-(send|recv)pipe)' size:bytes
+  '[i-]rtt'       time:ms
+  -rttvar         rttvar
+  -mtu            mtu
+  '(dev|-ifscope|-ifp)'  interface
+  -ifa            address
+  -expire         time:epoch
+  -hopcount       hopcount
+  -tag            tag
+  -prefixlen      bits
+  '-(label|push|pop|swap)' label
+  -priority       number  # is it a number
+  -secattr        secattr
+  '(-iw|-iwmax|-msl)' value
+  '-fib'          table
+)
+
+case $OSTYPE in
+  ^linux*)
+    args+=( '(-v)-q[suppress all output]' )
+    families=( -inet -inet6 )
+    modifiers+=(
+      '-dst:distinguish a destination'
+      '-gateway:distinguish a gateway address'
+      -netmask
+      -rtt -rttvar
+      -sendpipe -recvpipe
+      -mtu -hopcount
+      -expire
+      '-lock' '-lockrest'
+      -i{,nter}face:'indicate destination is directly reachable'
+      '-static:manually added route'
+      '-nostatic:pretend route added by kernel or daemon'
+      '-reject:emit an ICMP unreachable when matched'
+      '-blackhole:silently discard packets (during updates)'
+      '-proto1:set protocol specific routing flag #1'
+      '-proto2:set protocol specific routing flag #2'
+    )
+    sequential=( target gateway netmask )
+  ;|
+  *bsd*|darwin*|dragonfly*)
+    modifiers+=(
+      -link '-ifp' '-ifa' # do these need an argument: interface or address
+      '-prefixlen:indicate mask bits'
+    )
+  ;|
+  (net|free)bsd*|darwin*|dragonfly*)
+    families+=( -xns )
+    modifiers+=( '-xresolve:emit mesg on use (for external lookup)' )
+  ;|
+  (net|open)bsd*|darwin*|dragonfly*)
+    modifiers+=(
+      '-cloning:generate a new route on use'
+      '-llinfo:validly translate proto addr to link addr'
+    )
+  ;|
+  (open|free)bsd*|darwin*|dragonfly*)
+    args+=(
+      "-d[debug-only mode: don't update routing table]"
+      '-t[test-only mode: /dev/null used instead of a socket]'
+    )
+  ;|
+  netbsd*|solaris*)
+    args+=( '-f[remove all routes first]' )
+  ;;
+  (netbsd|darwin|dragonfly)*)
+    modifiers+=( '-proxy:make entry a link level proxy' )
+  ;|
+  (netbsd|openbsd|dragonfly)*)
+    subcmds+=( show 'print out the routing table' )
+    families+=( -mpls )
+  ;|
+  (netbsd|darwin)*)
+    families+=( -atalk )
+  ;|
+  (freebsd|darwin)*)
+    families+=( -osi )
+  ;|
+  (openbsd|dragonfly)*)
+    modifiers+=( -push -pop -swap )
+  ;|
+  freebsd*)
+    subcmds+=(
+      del $subcmds[delete]
+      show $subcmds[get]
+    )
+    args+=(
+      '(-6)-4[specify IPv4 address family]'
+      '(-4)-6[specify IPv6 address family]'
+    )
+    families+=( -4 -6 )
+    modifiers+=( '-fib:specify a routing table' )
+  ;;
+  netbsd*)
+    subcmds+=( flushall 'remove all routes including the default gateway' )
+    args+=(
+      '-S[print a space when a flag is missing to align flags]'
+      '-s[suppress all output from get except for the gateway]'
+    )
+    modifiers+=(
+      '-tag'
+      '-noreject:clear reject flag'
+      '-noblackhole:clear blackhole flag'
+    )
+  ;;
+  openbsd*)
+    subcmds+=( exec 'execute a command with alternate routing table' )
+    args+=(
+      '-T+[select specified alternate routing table]:table id'
+    )
+    modifiers+=(
+      -sa
+      '-label'
+      '-priority'
+      '-mpath:multiple gateways for a destination exist'
+      -mplslabel -in -out
+    )
+  ;;
+  solaris*)
+    subcmds+=( show 'display list of routes applied at system startup' )
+    args+=(
+      '-p[make changes to the route tables persistent across system restarts]'
+      '-R+[specify alternate root directory where changes are applied]:directory:_directories'
+    )
+    modifiers+=(
+      "-private:don't advertise this route"
+      '-multirt:create the specified redundant route'
+      '-setsrc:assign the default source address'
+      '-secattr:security attributes'
+    )
+  ;;
+  darwin*)
+    modifiers+=( -ifscope )
+  ;|
+  dragonfly*)
+    modifiers+=( -iw -iwmax -msl )
+  ;|
+  linux*)
+    args+=(
+      '(H -n)--numeric[output addresses numerically]'
+      '(H)*'{-e,--extend}'[display other/more information]'
+      '!(H -C --cache)'{-F,--fib}
+      '(H -C --cache)'{-C,--cache}'[display routing cache instead of FIB]'
+      + '(family)'
+      '-A+[use specified address family]:address family:(inet inet6 ax25 netrom ipx ddp x25)'
+      -4 -6 --inet --inet6 --ax25 --netrom --ipx --ddp --x25
+      + '(H)'
+      '(1 *)'{-h,--help}'[display help information]'
+      '(1 *)'{-V,--version}'[display version information]'
+    )
+    subcmds[del]=$subcmds[delete]
+    unset 'subcmds[monitor]' 'subcmds[get]' 'subcmds[change]'
+    modifiers+=(
+      netmask gw metric mss window irtt reject mod dyn reinstate
+      'dev:force route to be associated with the specified device'
+    )
+    sequential=( target interface )
+  ;;
+esac
+
+print -v sub -f '%s\\:%s' ${(kvq)subcmds}
+_arguments -C -s -S "1:command:(($sub))" '*::args:->args' $args && ret=0
+
+[[ -n $opt_args[(i)-[46]] ]] && families=()
+
+if [[ -n $state ]]; then
+  if [[ $line[1] = exec ]]; then
+    shift words
+    (( CURRENT-- ))
+    _normal
+  elif [[ $line[1] = (flush|monitor) ]]; then
+    sequential=()
+  fi
+
+  for ((i=2;i<CURRENT;i++)); do
+    if [[ -n $expect ]]; then
+      sequential=( ${sequential:#$expect} )
+      expect=''
+      continue
+    fi
+
+    expect=${params[(K)$words[i]]}
+    if [[ -n $expect ]]; then
+      ignore+=( ${(Q)words[i]} )
+    else
+      if [[ -n ${(M)${families%%:*}:#${(q)words[i]}} ]]; then
+        families=()
+      elif [[ -n ${(M)${modifiers%%:*}:#${(q)words[i]}} ]]; then
+	ignore+=( ${(q)words[i]} )
+      elif [[ $words[1] != -lock ]]; then
+	shift sequential
+      fi
+    fi
+  done
+
+  [[ -z $expect ]] && tags=( modifiers families )
+  _tags values $tags
+  while _tags; do
+    if _requested values; then
+      case ${expect:-$sequential[1]} in
+	target)
+	  if [[ -z $expect ]]; then
+	    _wanted -x targets expl target compadd default && ret=0
+	  else
+	    _message -e targets target
+	  fi
+	;;
+	interface) _net_interfaces && ret=0 ;;
+	size:bytes) _guard "[0-9]#" 'size (bytes)' ;; # _guard usage pointless
+	time:ms) _guard "[0-9]#" 'time (ms)' ;;
+	time:microseconds) _guard "[0-9]#" 'time (microseconds)' ;;
+	time:epoch) _guard "[0-9]#" 'expiration time (seconds since epoch)' ;;
+	rttvar) _guard "[0-9]#" 'time variance (microseconds)' ;;
+	mtu) _guard "[0-9]#" 'max MTU (bytes)' ;;
+	hopcount) _guard "[0-9]#" 'hop count' ;;
+	ssthresh) _message -e threshold 'ss threshold' ;;
+	bits) _guard "[0-9]#" 'bits' ;;
+	*) _guard "[^-]#" "${expect:-$sequential[1]}" ;;
+      esac
+    fi
+    _requested modifiers && _describe -t modifiers modifier modifiers -F ignore && ret=0
+    _requested families expl 'address family' compadd -a families && ret=0
+    (( ret )) || break
+  done
+fi
+
+return ret