diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2017-09-12 23:22:34 +0200 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2017-09-12 23:22:34 +0200 |
commit | 4aaf06e6678dcead65d7226bd6bde3cffeb2cb2e (patch) | |
tree | 5c8e2ac2c9a85e2e6568aed7120372e6efa074ac | |
parent | f33de64abf57611e59df72da230f3d0d6760c4c5 (diff) | |
parent | 6ff4787e830f8edb3a7e32490a88a131e4b62f7f (diff) | |
download | zsh-4aaf06e6678dcead65d7226bd6bde3cffeb2cb2e.tar.gz zsh-4aaf06e6678dcead65d7226bd6bde3cffeb2cb2e.zip |
Merge tag 'zsh-5.4.2' into debian
Release 5.4.2
36 files changed, 1579 insertions, 366 deletions
@@ -1,5 +1,101 @@ +2017-08-27 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * unposted: Config/version.mk: 5.4.2. + +2017-08-25 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * 41599: README, Etc/FAQ.yo: updates for 5.4.2. + +2017-08-25 William da Silva <w.vigolodasilva@gmail.com> + + * 41602 (tweaked): Completion/Unix/Command/_gpg: Improve wording + in gpg completion. + +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 + + * 41598: Completion/Unix/Command/_w, + Completion/Unix/Command/_who: new who and w completions + +2017-08-24 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * 41590 (modified as per 41595): README, Doc/Zsh/options.yo, + Src/exec.c, Src/init.c, Src/loop.c, Src/signals.c, Src/zsh.h, + Test/E01options.ztst: make ERR_RETURN work within each function + context, leaving ERR_EXIT global. + +2017-08-22 Daniel Shahaf <d.s@daniel.shahaf.name> + + * 41565: Functions/VCS_Info/VCS_INFO_patch2subject: vcs_info + patch2subject: Support `svn log -r N --diff` output. + +2017-08-18 Oliver Kiddle <opk@zsh.org> + + * 41568: Completion/Unix/Command/_vmstat: handle vmstat options + on NetBSD and Solaris and add some exclusion lists + + * 41563: Completion/Base/Utility/_regex_words: fix completion + description alignment with _regex_words + + * 41562: Completion/BSD/Command/_rcctl: correct completed word + + * 41561: Completion/Unix/Command/_dhclient: handle Free/OpenBSD + and bring options up-to-date for the ISC implementation + + * 41560: Completion/Unix/Command/_chsh: cleanup chsh completion + for different platforms + +2017-08-16 Oliver Kiddle <opk@zsh.org> + + * Tomasz Pala: users/22834: Completion/Linux/Command/_modutils: + fix irritating bug in file glob for Linux kernel modules + + * Tomasz Pala: users/22834: Completion/Unix/Command/_ip: + allow completion after -c and a few other new options + + * 41556: Completion/Solaris/Command/_snoop + Completion/Unix/Command/_ngrep, Completion/Unix/Command/_tcpdump, + Completion/Unix/Type/_bpf_filters: complete BPF (libpcap) filters + + * 41552: Completion/Unix/Command/_git: complete only branches + after git worktree add --detach because the --detach is + superfluous for other commits + +2017-08-15 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * posted twice but has not shown up: Src/exec.c, Src/zsh.h: + record file desriptors that remain open to save ones in the + range 0 to 9 in fdtable and close them on forking. + +2017-08-14 Peter Stephenson <p.stephenson@samsung.com> + + * Phil: 4152: Src/Modules/pcre.c, Test/V07pcre.ztst: fix big + with uninititialised memory in logic for extracting matched + parentheses. + +2017-08-11 Peter Stephenson <p.stephenson@samsung.com> + + * Phil: 41527 (tweak to use heap memory): Src/module.c, + Test/V07pcre.ztst: fix [[ ... ]]] conditions passed to modules. + +2017-08-09 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * unposted: README: 5.4,1 typo fixed. + + * 41504: Src/lex.c, Src/parse.c, Test/A01grammar.ztst: make + empty strings work in case patterns with no opening + parenthesis. + 2017-08-08 Peter Stephenson <p.w.stephenson@ntlworld.com> + * unposted: Config/version.mk: update to 5.4.1-dev-0. + * unposted: Config/verson.mk, README, Etc/FAQ.yo: update to version 5.4.1. diff --git a/Completion/BSD/Command/_rcctl b/Completion/BSD/Command/_rcctl index 0a030f486..62cb8f634 100644 --- a/Completion/BSD/Command/_rcctl +++ b/Completion/BSD/Command/_rcctl @@ -23,7 +23,7 @@ case $service in ':variable:compadd -a variables' ;; ls) - _arguments ':display a list of services and daemons matching:(all faulty off on started stopped)' + _arguments ':display a list of services and daemons matching:(all failed off on started stopped)' ;; order) _arguments \ diff --git a/Completion/Base/Utility/_regex_words b/Completion/Base/Utility/_regex_words index 62c2491bb..90b4a9735 100644 --- a/Completion/Base/Utility/_regex_words +++ b/Completion/Base/Utility/_regex_words @@ -1,6 +1,6 @@ #autoload -local opt OPTARG +local opt OPTARG matches end local term=$'\0' while getopts "t:" opt; do @@ -31,19 +31,22 @@ fi integer i local -a wds +if [[ $term = $'\0' ]]; then + matches=":${tag}:${desc}:(( " + end="))" +else + matches=":${tag}:${desc}:_values -s ${(q)term} ${(q)desc}" +fi + for (( i = 1; i <= $#; i++ )); do wds=(${(s.:.)argv[i]}) reply+=(/${wds[1]//\**/"[^$term]#"}"$term"/) if [[ $term = $'\0' ]]; then - reply+=(":${tag}:${desc}:(( ${wds[1]//\*}:${wds[2]//(#m)[: \(\)]/\\$MATCH} ))") + matches+="${wds[1]//\*}${wds[2]:+\\:${wds[2]//(#m)[: \(\)]/\\$MATCH}} " else - reply+=(":${tag}:${desc}:_values -s ${(q)term} ${(q)desc} \ -${(q)${${wds[1]//\*}//(#m)[:\[\]]/\\$MATCH}}\\[${(q)${wds[2]//(#m)[:\[\]]/\\$MATCH}}\\]") + matches+=" ${(q)${${wds[1]//\*}//(#m)[:\[\]]/\\$MATCH}}\\[${(q)${wds[2]//(#m)[:\[\]]/\\$MATCH}}\\]" fi eval "reply+=($wds[3])" - if (( $i == $# )); then - reply+=(\)) - else - reply+=(\|) - fi + reply+=(\|) done +reply+=( /'[]'/ "${matches}${end}" \) ) diff --git a/Completion/Linux/Command/_modutils b/Completion/Linux/Command/_modutils index 7de97f60e..5aa4c9cc7 100644 --- a/Completion/Linux/Command/_modutils +++ b/Completion/Linux/Command/_modutils @@ -107,7 +107,7 @@ _modutils() { if _cache_invalid modules-$kver || ! _retrieve_cache modules-$kver; then # 2011-01-02 gi1242: Do we need .o files? Or is .ko enough? - modules=( $modules_dir/$kver/(*~(source|build))/**/*.(o|ko|ko.gz|.ko.xz)(.:t:r:r) ) + modules=( $modules_dir/$kver/(*~(source|build))/**/*.(o|ko|ko.gz|ko.xz)(.:t:r:r) ) _store_cache modules-$kver modules fi diff --git a/Completion/Solaris/Command/_snoop b/Completion/Solaris/Command/_snoop index f734c2fb1..77798a730 100644 --- a/Completion/Solaris/Command/_snoop +++ b/Completion/Solaris/Command/_snoop @@ -1,87 +1,32 @@ #compdef snoop -_snoop() { - local -a t_opt exp +local -a args -t_opt=( - "r"\:"time relative to first packet" - "a"\:"absolute time" - "d"\:"delta time - time since receiving previous packet" +[[ $OSTYPE = solaris2.<11-> ]] && args=( + '-I+[capture packets from specified interface]:interface:_net_interfaces' ) - -exp=( - "ether" - "ethertype" - "host" - "from" - "to" - "ip" - "ip6" - "arp" - "rarp" - "pppoe" - "pppoed" - "pppoes" - "vlan" - "vlan-id" - "broadcast" - "multicast" - "bootp" - "dhcp" - "dhcp6" - "apple" - "decnet" - "greater" - "less" - "udp" - "tcp" - "icmp" - "icmp6" - "ah" - "esp" - "net" - "port" - "rpc" - "zone" - "ldap" - "gateway" - "nofrag" - ">" - ">=" - "<" - "<=" - "=" - "!=" - "and" - "or" - "not" - "slp" - "sctp" - "ospf" -) - - _arguments \ - '-a[generate audio signal on receiving packets]' \ - '-c[quit after capturing maxcount packets]:maxcount' \ - '-d[capture packets from specified device]:device:_net_interfaces' \ - '-i[display packets previously captured to file]:file:_files' \ - '-n[use file as IP address-to-name mapping table]:file:_files' \ - '-o[save captured packets to file]:file:_files' \ - '-p[display one or more packets from captured file]:first packet number [ , last packet number]' \ - '-q[do not display packet counter when capturing to file]' \ - '-r[do not resolve IP addresses to names]' \ - '-s[truncate each packet after snaplen bytes]:snaplen' \ - '-t[time-stamp presentation]:time-stamp mode:(($t_opt))' \ - '-C[list code generated from filter expression]' \ - '-D[display number of packets dropped on the summary line]' \ - '-N[create IP-address-to-name mapping table file (used with -i)]' \ - '-I[capture packets from specified interface]:interface:_net_interfaces' \ - '-P[capture packets in non-promiscuous mode]' \ - '-S[display size of the entire link layer frame in bytes]' \ - '-V[verbose summary mode]' \ - '-v[verbose mode]' \ - '-x[display offset and length of packet in HEX and ASCII]:offset [ , length]' \ - '*:expression:(($exp))' \ -} - -_snoop "$@" +_arguments -s -S -A "-*" \ + '-a[generate audio signal on receiving packets]' \ + '-c+[quit after capturing specified number of packets]:number of packets' \ + '-d+[capture packets from specified device]:device:_net_interfaces' \ + '-i+[display packets previously captured to file]:file:_files' \ + '-n+[use file as IP address-to-name mapping table]:file:_files' \ + '-o+[save captured packets to file]:file:_files' \ + '-p+[display one or more packets from captured file]:first packet number [ , last packet number]' \ + "-q[don't display packet counter when capturing to file]" \ + "-r[don't resolve IP addresses to names]" \ + '-s[truncate each packet after specified number of bytes]:length (bytes)' \ + '-t+[specify time-stamp presentation]:time-stamp mode:(( + r\:relative\ to\ first\ packet + a\:absolute + d\:delta\ -\ since\ previous\ packet + ))' \ + '-C[list code generated from filter expression]' \ + '-D[display number of packets dropped on the summary line]' \ + '-N[create IP-address-to-name mapping table file (used with -i)]' \ + '-P[capture packets in non-promiscuous mode]' \ + '-S[display size of the entire link layer frame in bytes]' \ + '-V[verbose summary mode]' \ + '-v[verbose mode]' \ + '-x+[display offset and length of packet in HEX and ASCII]:offset [ , length]' \ + '*::expression:= _bpf_filters' 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/_chsh b/Completion/Unix/Command/_chsh index 97552e3ac..006aa82a1 100644 --- a/Completion/Unix/Command/_chsh +++ b/Completion/Unix/Command/_chsh @@ -1,40 +1,67 @@ #compdef chsh chpass + +local variant help=h +local -a args shells + case $OSTYPE in -(darwin*|*bsd*) - _arguments : \ - '-s[Specify user login shell]:shell:(${(Z+Cn+)"$(</etc/shells)"})' \ - "-l[Specify location of user]:node:" \ - "-u[Specify authentication name]:auth user:" \ - "1:user name:_users" + darwin*|*bsd*) + args=( '(-a)-s[specify new login shell]:shell:($shells)' ) + ;| + (free|net|open)bsd*) + args+=( '(-s 1)-a[specify user database entry]:passwd entry' ) + ;| + darwin*) + args+=( + '-l[specify location of user]:location' + '-u[specify authentication name]:auth user' + ) ;; -(linux-gnu) - if { =chsh -v } >&/dev/null - then - local -a opts shells - shells=( $(=chsh -l) ) - _arguments : \ - "(-)-s[Specify your login shell]:shell:($shells)" \ - "(-)--shell[Specify your login shell]:shell:($shells)" \ - "(-)-l[Print shells in /etc/shells]" \ - "(-)--list-shells[Print shells in /etc/shells]" \ - "(-)-u[Print a usage message and exit]" \ - "(-)--help[Print a usage message and exit]" \ - "(-)-v[Print version information and exit]" \ - "(-)--version[Print version information and exit]" \ - "1:user name:_users" - return - fi - # else fall through - ;& -(*) - local s='' - # Use $s to cause all options to be treated as mutually exclusive - [[ $words[CURRENT-1] = -* ]] && s="(-)$words[CURRENT-1]" - # This fiddling with $s is a hack to cause "_arguments : --" to use - # the /etc/shells listing for -s or --shell even when the description - # of that option has been pulled from the GNU --help output. - [[ $words[CURRENT-1] = (-s|--shell) ]] && - s="$s"'[ ]:shell:(${(Z+Cn+)"$(</etc/shells)"})' - _arguments : $s "1:user name:_users" -- + (free|net)bsd*) + args+=( + '(-y)-l[update only the local password file]' + '(-l)-y[force YP database entry to be changed]' + ) + ;| + freebsd*) + args+=( + '-p[specify encrypted password field]:password hash' + '-e[change account expire time]:expiry time' + '-d[specify NIS domain]:domain' + '-h[specify NIS server to query]:NIS server:_hosts' + '-o[force use of RPC-based updates]' + ) + ;; + (linux-gnu) + _pick_variant -r variant util-linux=util-linux suse=pwdutils debian -v + args=( -S : '(-)'{-s+,--shell=}'[specify new login shell]:shell:($shells)' ) + case $variant in + suse|util-linux) + shells=( $(_call_program shells $words[1] -l) ) + args+=( + '(-)'{-l,--list-shells}'[print shells in /etc/shells]' + '(-)'{-v,--version}'[display version information]' + ) + help=u + ;| + util-linux|debian) + args+=( '(-)-'{$help,-help}'[display help information]' ) + ;| + suse) + args+=( + '(-)'{-u,--usage}'[display short usage message]' + '(-)--help[display help information]' + '(-D --binddn)'{-D+,--binddn=}'[specify LDAP disingushed name to bind]:binddn' + '(-P --path)'{-P+,--path=}'[specify path to search for passwd and shadow files]:path:_directories' + '(-q --quiet)'{-q,--quiet}"[don't be verbose]" + '--service=[use specified name service]:service:(files nis nisplus ldap)' + ) + ;; + debian) + args+=( '(-R --root)'{-R+,--root=}'[specify directory to chroot into]:directory:_directories' ) + ;; + esac ;; esac + +(( $#shells )) || shells=( ${(Z+Cn+)"$(</etc/shells)"} ) +_arguments $args '1:user name:_users' diff --git a/Completion/Unix/Command/_dhclient b/Completion/Unix/Command/_dhclient index dafe299d9..10cb551e0 100644 --- a/Completion/Unix/Command/_dhclient +++ b/Completion/Unix/Command/_dhclient @@ -2,27 +2,69 @@ local args -if _pick_variant three=V3 two --help; then - args=( - '-q[quiet]' - '-1[only try once to get a lease]' - '-r[release the current lease]' - '-lf[lease file]:lease file:_files' - '-pf[pid file]:pid file:_files' - '-cf[config file]:config file:_files' - '-sf[script file]:script file:_files' - '-e[env vars to pass to child processes]:env var key value pairs:' - '-s[transmit to specific target instead of broadcast]:server:_hosts' - '-g[force giaddr field]:relay:_hosts' - '-n[do not configure any interfaces]' - '-nw[daemonize immediately rather than wait for IP acquisition]' - '-w[do not exit if there are no interfaces found to configure]' - ) -else - args=( '-e[exit if configuration failed after a certain time]' ) -fi +case $OSTYPE in + (open|free)bsd*) + args+=( + '-c+[specify configuration file]:file:_files' + '-l+[specify leases file]:file:_files' + '-u[reject leases with unknown options]' + ) + ;| + freebsd*) + args+=( + '(-d)-b[immediately move to the background]' + '-p+[specify PID file]:file:_files' + ) + ;; + openbsd*) + args+=( + '-i+[ignore values provided by leases for specified options]:options' + '-L+[specify file to write option data too]:file:_files' + ) + ;; + *) # ISC implementation, used on Linux and NetBSD + args=( + '!(-6 -S -T -P -D -N)-4' + '(-4 -s)-6[use the DHCPv6 protocol]' + '-1[only try once to get a lease]' + '(-d)-nw[daemonize immediately rather than wait for IP acquisition]' + "-m[don't require responding ethernet address of dhcp server to match expectation]" + '-v[verbose log messages]' + "-w[don't exit if there are no interfaces found to configure]" + "-n[don't configure any interfaces]" + '-e[specify env vars to pass to child processes]:env var key value pairs' + '(-x)-r[release the current lease]' + '(-r)-x[stop the running DHCP client without releaseing current lease]' + '-p[specify port to transmit to / listen on]:port:_ports' + '(-6)-s[transmit to specific target instead of broadcast]:server:_hosts' + '-g[force giaddr field]:relay:_hosts' + '-i[use a DUID with DHCPv4 clients]' + '-I[use the standard DDNS scheme]' + '--version[display version number]' + '(-4)-S[use Information-request to get only stateless configuration]' + '(-4)*-T[ask for IPv6 temporary addresses]' + '(-4)-P[enable IPv6 prefix delegation]' + '-D[specify DUID selection method]:DUID:((LL\:link-layer LLT\:link-layer\ plus\ timestamp))' + '(-4)-N[restore normal address query for IPv6]' + '-lf[lease file]:lease file:_files' + '(--no-pid)-pf[pid file]:pid file:_files' + '(-pf)--no-pid[disable writing pid files]' + '-cf[config file]:config file:_files' + '-sf[script file]:script file:_files' + '-4o6[DHCPv4 over DHCPv6 protocol]:port' + "-nc[don't drop capabilities]" + '-B[set the BOOTP broadcast flag in request packets]' + '-C[specify dhcp-client-identifier option]:option' + '(-F)-H[specify host-name option]:host name:_hosts' + '(-H)-F[specify fully qualified hostname option]:host name:_hosts' + '-V[specify vendor-class-identifier option]:option' + '--request-options[specify list of options the client is to request from the server]:options' + '--timeout[specify time after which dhclient will decide that no DHCP servers can be contacted]:timeout' + ) + ;; +esac -_arguments $args \ - '-p[port to transmit to / listen on]:_ports' \ - '-d[force to run in foreground]' \ +_arguments -s -S -A "-*" $args \ + '-q[quiet]' \ + '(-b -nw)-d[remain as a foreground process]' \ ':interface:_net_interfaces' diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 518e6d198..26554de05 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -2027,9 +2027,9 @@ _git-worktree() { case $line[1] in (add) if (( $words[(I)--detach] )); then - args=( ':commit:__git_commits' ) - else args=( ':branch:__git_branch_names' ) + else + args=( ':commit:__git_commits' ) fi _arguments \ '(-f --force)'{-f,--force}'[checkout branch even if already checked out in another worktree]' \ diff --git a/Completion/Unix/Command/_gpg b/Completion/Unix/Command/_gpg index fe6084f20..d7a8ece4c 100644 --- a/Completion/Unix/Command/_gpg +++ b/Completion/Unix/Command/_gpg @@ -26,7 +26,7 @@ fi [[ $service = gpgv ]] || args+=( '(-e --encrypt)'{-e,--encrypt}'[encrypt data. this option may be combined with --sign]' {-d,--decrypt}'[decrypt file or stdin]' - '(-c --symmetric)'{-c,--symmetric}'[encrypt with symmetric cypher only]' + '(-c --symmetric)'{-c,--symmetric}'[encrypt with symmetric cipher only]' '(-s --sign)'{-s,--sign}'[make a signature]' '*'{-r+,--recipient}'[specify user to encrypt for]:recipient:->public-keys' '(-u --local-user)'{-u+,--local-user}'[use name as the user ID to sign]:user attachment:_users' @@ -52,7 +52,7 @@ fi '--fingerprint[list all keys with their fingerprints]:key attachment:->public-keys' '--list-packets[list only the sequence of packets]' '--gen-key[generate a new pair key]' - '--edit-key[a menu for edit yours keys]:key attachment:->public-keys' + '--edit-key[interactively edit a key]:key attachment:->public-keys' '--sign-key[sign a key]:key attachment:->public-keys' '--lsign-key[sign a key but mark as non-exportable]:key attachment:->public-keys' '--delete-keys[remove key from public keyring]:key attachment:->public-keys' @@ -60,12 +60,12 @@ fi '--delete-secret-and-public-keys:key attachment:->secret-keys' '--gen-revoke[generate a revocation certificate]' '--desig-revoke[generate a designated revocation certificate]' - '--export[export all key from all keyrings]' + '--export[export all keys from all keyrings]' '--send-keys[send keys to a keyserver]:key attachment:->public-keyids' '--export-secret-keys:key attachment:->secret-keys' '--export-secret-subkeys:key attachment:->secret-keys' - '--import[import a gpg key from a file]:_files attachment:_files' - '--fast-import[import a file without build trustdb]:_files attachment:_files' + '--import[import a gpg key from a file]:attachment (file):_files' + '--fast-import[import a file without adding to trustdb]:attachment (file):_files' '--fetch-keys[fetch key at URIs]:uri:' '--recv-keys[receive a list of keys from a keyserver]:key attachment:->public-keyids' '--refresh-keys[update all keys from a keyserver]' @@ -82,7 +82,7 @@ fi '--gen-random:count' '--gen-prime' '--warranty[print warranty info]' '(-a --armor)'{-a,--armor}'[create ASCII armored output]' - '--default-key[specify default user-id for signatures]:key:->secret-keys' + '--default-key[specify default user ID for signatures]:key:->secret-keys' '--default-recipient[specify default recipient]:recipient:->public-keys' '--default-recipient-self[use default key as default recipient]' '--no-default-recipient[reset default recipient]' diff --git a/Completion/Unix/Command/_ip b/Completion/Unix/Command/_ip index 6e1cc3b78..74101c646 100644 --- a/Completion/Unix/Command/_ip +++ b/Completion/Unix/Command/_ip @@ -530,15 +530,30 @@ args=( /$'[^\0]#\0'/ ) +# TODO: +# -b*atch <FILENAME> +# -force (for batch mode) +# -l*oops <COUNT> +# -n*etns <NETNS> +# -rc, -rcvbuf<SIZE> _regex_words options "ip options" \ '-h*uman:output statistics with human readable values' \ '-i*ec:print human readable rates in IEC units (ie. 1K = 1024)' \ '-s*tatistics:output statistics' \ + '-d*etails:output more detailed information' \ + '-c*olor:color output' \ + '-a*ll:executes specified command over all objects' \ '-f*amily:select protocol family:$subcmd_family' \ '-4:IPv4' \ '-6:IPv6' \ + '-B:family bridge' \ + '-D:family DECnet' \ + '-I:family IPX' \ + '-M:family MPLS' \ '-0:link protocol, no networking' \ '-o*neline:output one record per line' \ + '-t*imestamp:display current time when using monitor option' \ + '-ts*hort:display current time in shorter format when using monitor option' \ '-r*esolve:use system resolver for DNS names' args+=("$reply[@]" "#") diff --git a/Completion/Unix/Command/_mpc b/Completion/Unix/Command/_mpc index e0c6888b0..fee5e06f4 100644 --- a/Completion/Unix/Command/_mpc +++ b/Completion/Unix/Command/_mpc @@ -1,4 +1,4 @@ -#compdef mpc +#compdef mpc -value-,MPD_HOST,-default local OUT foo MPD_MUSIC_DIR MPC_PLAYLIST_MATCHER MPC_FORMAT_STRING @@ -26,13 +26,17 @@ _mpc_command() { mpc_cmds=( add:"append a song to the end of the current playlist" + cdprev:"compact disk player-like previous command" + channels:"list the channels that other clients have subscribed to" clear:"clear the current playlist" + clearerror:"clear the current error" crop:"remove all songs except for the currently playing song" current:"show the currently playing song" crossfade:"set and display crossfade settings" del:"remove a song from the current playlist" - disable:"disable a output" - enable:"enable a output" + disable:"disable an output" + enable:"enable an output" + toggleoutput:"toggle an output" idle:"wait until an event occurs" idleloop:"loop waiting for events" insert:"insert a song after the currently playing song in the playlist" @@ -40,6 +44,8 @@ _mpc_command() { load:"load file as a playlist" ls:"list the contents of specified directory" lsplaylists:"list currently available playlists" + mixrampdb:"set and display mixrampdb settings" + mixramdelay:"set and display mixrampdelay settings" move:"move song in playlist" next:"play the next song in the current playlist" outputs:"show the current outputs" @@ -51,10 +57,14 @@ _mpc_command() { repeat:"toggle repeat mode, or specify state" single:"toggle single mode, or specify state" consume:"toggle consume mode, or specify state" + replaygain:"set or display the replay gain mode" rm:"remove a playlist" save:"save a playlist to file" search:"search for a song" + searchadd:"search songs and add them to the current playlist" + searchplay:"search and play songs from the current playlist" find:"search for a song, exact match" + findadd:"find songs and add them to the current playlist" list:"list all tags of given type" seek:"seek to the position specified in percent" shuffle:"shuffle the current playlist" @@ -65,13 +75,18 @@ _mpc_command() { version:"report version of MPD" volume:"set volume" status:"display MPD status" + sendmessage:"send a message to the specified channel" + waitmessage:"wait for at least one message on the specified channel" + subscribe:"subscribe to the specified channel and continuously receive messages" + sticker:"sticker management" ) if (( CURRENT == 1 )); then - _describe -t commands "mpc command" mpc_cmds + _describe -t commands "mpc command" mpc_cmds || \ + _wanted commands expl "mpc command" compadd loadtab tab lstab else local cmd=$words[1] - local curcontext="${curcontext%:*}:mpc-${cmd}" ret=1 + local curcontext="${curcontext%:*:*}:mpc-${cmd}:" ret=1 if ! _call_function ret _mpc_$cmd; then _default && ret=0 fi @@ -100,13 +115,13 @@ _mpc_helper_songnumbers() { NM="$compstate[nmatches]" fi - out=("${(@f)$(_call_program song-numbers mpc $foo playlist)}") + out=("${(@f)$(_call_program song-numbers $mpccmd $foo playlist)}") out=("${(@M)out[@]:#${~MATCH}}") sn=("${(@)${(@M)out}//(#b)(#s)(\#|[ >]#)([0-9]#)*/$match[2]}") list=("${(@Mr:COLUMNS-1:)out}") - _wanted -V 'song numbers' expl 'song number' \ + _wanted -V song-numbers expl 'song number' \ compadd "$@" -ld list "$all[@]" -a sn && ret=0 if [[ -n "$all" ]]; then @@ -131,8 +146,8 @@ _mpc_helper_songnumbers() { (( $+functions[_mpc_helper_playlists] )) || _mpc_helper_playlists() { local list expl - list=(${(f)"$(mpc lsplaylists)"}) - _wanted list expl playlist compadd -M $MPC_PLAYLIST_MATCHER $expl -a list + list=(${(f)"$(_call_program playlists $mpccmd lsplaylists)"}) + _wanted playlists expl playlist compadd -M $MPC_PLAYLIST_MATCHER $expl -a list } (( $+functions[_mpc_helper_files] )) || @@ -142,12 +157,13 @@ _mpc_helper_files() { return fi - local -U list expl + local -U list expl prefix=$PREFIX if [[ $words[CURRENT] != */* ]]; then - list=( ${${(f)"$(mpc listall)"}%%/*}) + list=( ${${(f)"$(_call_program files $mpccmd listall)"}%%/*}) _wanted files expl file compadd -qS/ -a list else - list=(${(f)"$(mpc tab $words[CURRENT])"}) + [[ $compstate[quote] = [\'\"] ]] && prefix="$compstate[quote]$PREFIX$compstate[quote]" + list=(${(f)"$($mpccmd tab -- ${(Q)prefix} 2>/dev/null)"}) _wanted files expl file _multi_parts / list fi } @@ -159,12 +175,13 @@ _mpc_helper_directories() { return fi - local -U list expl + local -U list expl prefix=$PREFIX if [[ $words[CURRENT] != */* ]]; then - list=( ${${(M)${(f)"$(mpc listall)"}:#*/*}%%/*}) + list=( ${${(M)${(f)"$(_call_program directories $mpccmd listall)"}:#*/*}%%/*}) _wanted directories expl directory compadd -qS/ -a list else - list=(${(f)"$(mpc lstab $words[CURRENT])"}) + [[ $compstate[quote] = [\'\"] ]] && prefix="$compstate[quote]$PREFIX$compstate[quote]" + list=(${(f)"$($mpccmd lstab -- ${(Q)prefix} 2>/dev/null)"}) _wanted directories expl directory _multi_parts / list fi } @@ -172,7 +189,7 @@ _mpc_helper_directories() { (( $+functions[_mpc_helper_outputs] )) || _mpc_helper_outputs() { local vals outline - vals=(${${${${(M)${(f)"$(mpc outputs 2> /dev/null)"}:#Output * \(*\) is (en|dis)abled}##Output }%%\) is (en|dis)abled}/ \(/:}) + vals=(${${${${(M)${(f)"$(_call_program outputs $mpccmd outputs)"}:#Output * \(*\) is (en|dis)abled}##Output }%%\) is (en|dis)abled}/ \(/:}) _describe -t outputs output vals } @@ -200,6 +217,10 @@ _mpc_disable() { _mpc_helper_outputs } +_mpc_toggleoutput() { + _mpc_helper_outputs +} + _mpc_move() { if (( $#words <= 3 )); then _mpc_helper_songnumbers @@ -216,22 +237,41 @@ _mpc_ls() { _mpc_helper_directories } +_mpc_lstab() { + _mpc_helper_directories +} + _mpc_load() { _mpc_helper_playlists } +_mpc_loadtab() { + _mpc_helper_playlists +} + _mpc_save() { _mpc_helper_playlists } +_mpc_tab() { + _mpc_helper_files +} + _mpc_rm() { _mpc_helper_playlists } _mpc_volume() { - local expl - compset -P '[-+]' - _wanted list expl volume compadd $expl - {0..100} + local expl value="${${$(_call_program volume $mpccmd volume)#*:}%\%}" ret=1 + if [[ -prefix \+ && $value -lt 100 ]]; then + _wanted -V volume expl volume compadd $expl - +{1..$((100-value))} && ret=0 + elif [[ -prefix - && $value -gt 0 ]]; then + _wanted -V volume expl volume compadd $expl - -{1..$value} && ret=0 + else + _wanted -V volume expl volume compadd $expl - {0..100} && ret=0 + compstate[insert]=menu:$((value+1)) + fi + return ret } _mpc_repeat() { @@ -250,6 +290,10 @@ _mpc_consume() { _mpc_helper_bool } +_mpc_current() { + _arguments --wait +} + _mpc_search() { local list expl list=(album artist title track name genre date composer performer comment disc filename any) @@ -273,7 +317,28 @@ _mpc_update() { _mpc_helper_files } -_arguments \ - '--format[specify the format of song display]:format string' \ - '--no-status[prevent printing song status on completion]' \ - '*::mpc command:_mpc_command' +if [[ $service = *MPD_HOST* ]]; then + _hosts + return +fi + +local curcontext="$curcontext" state line expl ret=1 +local mpccmd="$words[1]" + +_arguments -C \ + '(-q --quiet --no-status -v --verbose)'{-v,--verbose}'[give verbose output]' \ + '(-q --quiet --no-status -v --verbose)'{-q,--quiet,--no-status}'[prevent printing song status on completion]' \ + '(-h --host)'{-h,--host=}'[connect to specified host]:_hosts' \ + '(-p --port)'{-p,--port=}'[connect to server port]:port' \ + '(-f --format)'{-f,--format=}'[specify the format of song display]:format string:->formats' \ + '(-w --wait)'{-w,--wait}'[wait for operation to finish (e.g. database update)]' \ + '*::mpc command:_mpc_command' && ret=0 + +if [[ $state = formats ]]; then + compset -P '([^%]|%[^%]#%)#' + _wanted metadata expl 'metadata delimiter' compadd -p % -S % \ + artist album albumartist comment composer date disc genre performer title \ + track time file position mtime mdate && ret=0 +fi + +return ret diff --git a/Completion/Unix/Command/_ngrep b/Completion/Unix/Command/_ngrep new file mode 100644 index 000000000..924597826 --- /dev/null +++ b/Completion/Unix/Command/_ngrep @@ -0,0 +1,33 @@ +#compdef ngrep + +_arguments -s -S \ + '(- 1 *)-h[display help information]' \ + '(- 1 *)-V[display version information]' \ + "-q[be quiet (don't print packet reception hash marks)]" \ + '-e[show empty packets]' \ + '-i[ignore case]' \ + '-v[invert match]' \ + "-R[don't do privilege revocation logic]" \ + '(-W)-x[print in alternate hexdump format]' \ + '-X[interpret match expression as hexadecimal]' \ + '-w[word-regex (expression must match as a word)]' \ + "-p[don't go into promiscuous mode]" \ + '-l[make stdout line buffered]' \ + '-D[replay pcap_dumps with their recorded time intervals]' \ + '-t[print timestamp every time a packet is matched]' \ + '-T[print delta timestamp every time a packet is matched specify twice for delta from first match]' \ + "-M[don't do multi-line match (do single-line match instead)]" \ + '(-d -s)-I+[read packet stream from pcap format file]:file:_files' \ + '-O+[dump matched packets in pcap format file]:file:_files' \ + '-n+[look at only specified number of packets]:packets' \ + '-A+[dump specified number of context packets after a match]:packets' \ + '(-I)-s+[set the bpf caplen]:length (bytes) [65535]' \ + '-S+[set the upper limit on size of packets matched]:size (bytes)' \ + '(-x)-W+[set the dump format]:packet display format:(normal byline single none)' \ + '-c+[force the column width to the specified size]:columns' \ + '-P+[set the non-printable display char to what is specified]:character [.]' \ + '-F+[read the bpf filter from the specified file]:file:_files' \ + '-N[show sub protocol number]' \ + '(-I)-d+[use specified device instead of the pcap default]:interface:_net_interfaces' \ + '1: :_guard "^-*" pattern' \ + '*::expression:_bpf_filters' 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 diff --git a/Completion/Unix/Command/_tcpdump b/Completion/Unix/Command/_tcpdump index 2c1d82226..4b9950fa5 100644 --- a/Completion/Unix/Command/_tcpdump +++ b/Completion/Unix/Command/_tcpdump @@ -1,17 +1,25 @@ #compdef tcpdump -typeset -A opt_args +local args ret=1 +local root +(( EUID )) && root='!' -_interfaces() { - local disp expl sep - _description interfaces expl 'network interface' - _net_interfaces "$expl[@]" - if zstyle -t ":completion:${curcontext}:interfaces" verbose; then - zstyle -s ":completion:${curcontext}:interfaces" list-separator sep || sep=-- - disp=( "any $sep capture on all interfaces" ) - compadd "$expl[@]" -ld disp any +_tcpdump_interfaces() { + local disp expl sep interfaces + [[ $OSTYPE != openbsd* ]] && + interfaces=( ${${${${(f)"$(_call_program interfaces tcpdump -D)"}#<->.}//[()]/}/ /:} ) + if (( $#interfaces )); then + _describe -t interfaces 'network interface' interfaces else - compadd "$expl[@]" any + _description interfaces expl 'network interface' + _net_interfaces "$expl[@]" + if zstyle -t ":completion:${curcontext}:interfaces" verbose; then + zstyle -s ":completion:${curcontext}:interfaces" list-separator sep || sep=-- + disp=( "any $sep capture on all interfaces" ) + compadd "$expl[@]" -ld disp any + else + compadd "$expl[@]" any + fi fi } @@ -40,43 +48,50 @@ _esp_secrets () { } _packet_types () { + local -a types types=( - 'cnfp[Cisco NetFlow protocol]' - 'rpc[Remote Procedure Call]' - 'rtp[Real-Time Applications protocol]' - 'rtcp[Real-Time Applications control protocol]' - 'vat[Visual Audio Tool]' - 'wb[distributed White Board]' + 'cnfp:Cisco NetFlow protocol' + 'rpc:Remote Procedure Call' + 'rtp:Real-Time Applications protocol' + 'rtcp:Real-Time Applications control protocol' + 'vat:Visual Audio Tool' + 'wb:distributed White Board' ) if [[ $OSTYPE = openbsd* ]]; then types+=( - 'sack[RFC 2018 TCP Selective Acknowledgements Options]' - 'vrrp[Virtual Router Redundancy Protocol]' - 'tcp[Transmission Control Protocol]' + 'sack:RFC 2018 TCP Selective Acknowledgements Options' + 'vrrp:Virtual Router Redundancy Protocol' + 'tcp:Transmission Control Protocol' ) else types+=( - 'aodv[Ad-hoc On-demand Distance Vector protocol]' - 'carp[Common Address Redundancy Protocol]' - 'radius[RADIUS]' - 'snmp[Simple Network Management Protocol]' - 'tftp[Trivial File Transfer Protocol]' - 'vxlan[Virtual eXtensible Local Area Network]' - 'zmtpl[ZeroMQ Message Transport Protocol]' + 'aodv:Ad-hoc On-demand Distance Vector protocol' + 'carp:Common Address Redundancy Protocol' + 'radius:RADIUS' + 'snmp:Simple Network Management Protocol' + 'tftp:Trivial File Transfer Protocol' + 'vxlan:Virtual eXtensible Local Area Network' + 'zmtpl:ZeroMQ Message Transport Protocol' ) fi - _values 'Packets type' $types + _describe -t packet-types 'packet type' types +} + +_time_stamp_types () { + local vals + vals=( ${${${(ps:\n :)"$(_call_program time-stamp-types tcpdump -J ${(kv)opt_args[(i)-i|--interface]} 2>&1)"}[2,-1]:#*cannot be set*}/ /:} ) + _describe -t time-stamp-types "time stamp type" vals } _data_link_types () { - if (( $+opt_args[-i] )); then - vals=( ${${${(s: :)"$(_call_program data-link-types tcpdump -L -i $opt_args[-i] 2>&1)"}[2,-1]}/ /:} ) - _describe -t data-link-types "data link types ($opt_args[-i])" vals && ret=0 - else - _values "Data link types (general)" \ - "EN10MB" \ - "LINUX_SLL" - fi + local vals expl + if (( $+opt_args[(i)-i|--interface] )); then + vals=( ${${${(s: :)"$(_call_program data-link-types tcpdump -L ${(kv)opt_args[(i)-i|--interface]} 2>&1)"}[2,-1]}/ /:} ) + _describe -t data-link-types "data link type (${(v)opt_args[(i)-i|--interface]})" vals + else + _wanted data-link-types expl "data link type (general)" \ + compadd EN10MB LINUX_SLL + fi } _bpf_filter () { @@ -84,79 +99,95 @@ _bpf_filter () { args=( '-A[print each packet in ASCII]' - '-c[exit after receiving specified number of packets]:number of packets' + '-c+[exit after receiving specified number of packets]:number of packets' '(-ddd)-d[dump the compiled packet-matching code in a human readable form]' '(-ddd)-dd[dump packet-matching code as a C program fragment]' '(-d -dd)-ddd[dump packet-matching code as decimal numbers (preceded with a count)]' "-E[decrypting IPsec ESP packets]:spi@ipaddr::algo\:secret:_esp_secrets" '-e[print the link-level header on each dump line]' - '-F[input file for the filter expression]:filter expression file:_files' + '-F+[specify input file for the filter expression]:filter expression file:_files' "-f[print 'foreign' IPv4 addresses numerically]" '-l[make stdout line buffered]' "-N[don't print domain name qualification of host names]" - "-n[don't convert addresses to names]" + "(-nn)-n[don't convert addresses to names]" "-O[don't run the packet-matching code optimizer]" - "-p[don't put the interface into promiscuous mode]" + '(-p --no-promiscuous-mode)'{-p,--no-promiscuous-mode}"[don't put the interface into promiscuous mode]" '-q[quick (quiet?) output]' - '-r[read packets from file]:input file:_files' - '-S[print absolute TCP sequence numbers]' - '-s[specify number of bytes of data to snarf from each packet]:number of bytes to snap' - '-T[interpret captured packets as specified type]:packet type:_packet_types' + '-r+[read packets from file]:input file:_files' + '(-S --absolute-tcp-sequence-numbers)'{-S,--absolute-tcp-sequence-numbers}'[print absolute TCP sequence numbers]' + '-T+[interpret captured packets as specified type]:packet type:_packet_types' "(-tt -ttt -tttt -ttttt)-t[don't print a timestamp on each dump line]" '(-t -ttt -tttt -ttttt)-tt[print an unformatted timestamp on each dump line]' '(-vv -vvv)-v[slightly more verbose output]' '(-v -vvv)-vv[more verbose output]' - '-w[write the raw packets to file]:output file:_files' + '-w+[write the raw packets to file]:output file:_files' '-X[print each packet (minus its link level header) in hex and ASCII]' '-x[print each packet (minus its link level header) in hex]' - '-y[set the data link type to use while capturing packets]:data link type:_data_link_types' - '*:BPF filter:_bpf_filter' + '(-y --linktype)'{-y+,--linktype=}'[set the data link type to use while capturing packets]: :_data_link_types' ) if [[ $OSTYPE = openbsd* ]]; then - args+=( + args=( + '-i+[specify interface]:interface:_tcpdump_interfaces' + - listd + '-L[list data link types for the interface]' + - capture + ${(R)args:#(|\*)(|\(*\))--*} # removes any long-options '(-n)-a[attempt to convert network and broadcast addresses to names]' '-D[select packet flowing in specified direction]:direction:(in out)' '-I[print the interface on each dump line]' '-o[print a guess of the possible operating system(s)]' + '-s+[specify amount of data to snarf from each packet]:length (bytes) [116]' '(-t -tt -tttt -ttttt)-ttt[print day and month in timestamp]' '(-t -tt -ttt -ttttt)-tttt[print timestamp difference between packets]' '(-t -tt -ttt -tttt)-ttttt[print timestamp difference since the first packet]' ) else - args+=( - '-B[specify the capture buffer size in KiB]:capture buffer size' + args=( + '(-i --interface -D --list-interfaces)'{-i+,--interface=}'[specify interface]:interface:_tcpdump_interfaces' + - listt + '(-J --list-time-stamp-types)'{-J,--list-time-stamp-types}'[list supported time stamp types]' + - listd + '(-L --list-data-link-types)'{-L,--list-data-link-types}'[list data link types for the interface]' + - capture + $args + '(-B --buffer-size)'{-B+,--buffer-size=}'[set the operating system capture buffer size]:size (kiB)' '-b[print the AS number in BGP packets in ASDOT notation]' - '-C[specify output file size in MB (10e6 bytes)]:output file size' - '(-* *)'-D'[print the list of the network interfaces available on the system]' - '-G[specify the interval to rotate the dump file in seconds]:dump file rotate seconds' + '-C+[specify output file size]:output file size (MB)' + '(-)'{-D,--list-interfaces}'[print the list of the network interfaces available on the system]' + '-G+[rotate dump file specified with -w at specified interval]:interval (seconds)' '-H[attempt to detect 802.11s draft mesh headers]' - '(-* *)-h[print version strings and a usage message]' + '(- *)'{-h,--help}'[display help information]' + '(- *)--version[display version information]' + '(-I --monitor-mode)'{-I,--monitor-mode}'[put the Wi-Fi interface in monitor mode]' + '--immediate-mode[deliver packets to tcpdump as soon as they arrive without buffering]' '-I[put the interface in monitor mode]' - '(-* *)-J[list the supported timestamp types]' - '-j[set the timestamp type]:timestamp type' - "-K[don't attempt to verify checksums]" - '*-m[load SMI MIB module definitions]:SMI MIB module definitions:_files' - '-M[shared secret for validating the digests in TCP segments with the TCP-MD5 option]:secret' - '-R[assume ESP/AH packets to be based on old specification (RFC1825 to RFC1829)]' - '(-t -tt -tttt)-ttt[print a delta (in micro-seconds) between current and previous line on each dump line]' - '(-t -tt -ttt)-tttt[print a timestamp in default format proceeded by date on each dump line]' - '(-t -tt -ttt -tttt)-ttttt[print a delta (micro-second resolution) since the first line on each dump line]' - '-U[make output packet-buffered when saving to file (-w)]' + '(-j --time-stamp-type)'{-j+,--time-stamp-type=}'[set the time stamp type for the capture]: :_time_stamp_types' + '--time-stamp-precision=[set the time stamp precision for the capture]:precision [micro]:(micro nano)' + '(-K --dont-verify-checksums)'{-K,--dont-verify-checksums}"[don't verify IP, TCP, or UDP checksums]" + '*-m+[load SMI MIB module definitions]:SMI MIB module definition:_files' + "(-n)-nn[don't convert protocol and port numbers to names]" + '-M+[specify shared secret for validating the digests in TCP segments with the TCP-MD5 option]:secret' + '(-# --number)'{-\#,--number}'[print an optional packet number at the beginning of the line]' + '(-O --no-optimize)'{-O,--no-optimize}"[don't run the packet-matching code optimizer]" + '(-s --snapshot-length)'{-s+,--snapshot-length=}'[specify amount of data to snarf from each packet]:length (bytes) [65535]' + '(-t -tt -tttt -ttttt)-ttt[print a delta (in micro-seconds) on each line since previous line]' + '(-t -tt -ttt -ttttt)-tttt[print a timestamp in default format preceded by date on each dump line]' + '(-t -tt -ttt -tttt)-ttttt[print a delta (in micro-seconds) on each line since first line]' + '(-U --packet-buffered)'{-U,--packet-buffered}'[make output packet-buffered when saving to file (-w)]' '-u[print undecoded NFS handles]' - '-V[Read a list of filenames from file]:file:_files' + '-V+[read a list of filenames from specified file]:file:_files' '(-v -vv)-vvv[most verbose output]' - '-W[limit the number of created files (-C)]:number of files' + '-W+[limit the number of created files (-C)]:number of files' '(-X)-XX[print each packet, including its link level header, in hex and ASCII]' '(-x)-xx[print each packet, including its link level header, in hex]' - '-Z[drops privileges (if root) and changes user ID (along with primary group)]:user:_users' - '-z[command to run after file rotation]:command:_command_names' + "${root}(-Z --relinquish-privileges)"{-Z+,--relinquish-privileges=}'[drop privileges and run as specified user]:user:_users' + '-z+[specify command to run on files (with -C or -G)]:command:_command_names -e' ) fi +[[ $OSTYPE = freebsd* ]] && args+=( + '-R[assume ESP/AH packets to be based on old specification (RFC1825 to RFC1829)]' +) -_arguments : \ - '-i[interface]:interface:_interfaces' \ - - optL \ - '-L[list the known data link types for the interface]' \ - - default \ - $args +_arguments -s $args \ + '*::BPF filter:= _bpf_filters' diff --git a/Completion/Unix/Command/_vmstat b/Completion/Unix/Command/_vmstat index 7082cbbd5..7d3008592 100644 --- a/Completion/Unix/Command/_vmstat +++ b/Completion/Unix/Command/_vmstat @@ -4,28 +4,31 @@ local -a specs case $OSTYPE in *linux*) specs=( - '(-a --active)'{-a,--active}'[active/inactive memory]' - '(-f --forks)'{-f,--forks}'[number of forks since boot]' - '(-m --slabs)'{-m,--slabs}'[slabinfo]' - '(-n --one-header)'{-n,--one-header}'[do not redisplay header]' - '(-s --stats)'{-s,--stats}'[event counter statistics]' - '(-d --disk)'{-d,--disk}'[disk statistics]' - '(-D --disk-sum)'{-D,--disk-sum}'[summarize disk statistics]' - '(-p --partition)'{-p,--partition}'[partition specific statistics]:partition:_files' - '(-S --unit)'{-S+,--unit}'[define display unit]:unit prefix:(( k\:1000 K\:1024 m\:1000000 M\:1048576 ))' '(-w --wide)'{-w,--wide}'[wide output]' '(-t --timestamp)'{-t,--timestamp}'[show timestamp]' - '1:delay' '2:count' + '(-n --one-header)'{-n,--one-header}'[do not redisplay header]' + '(-S --unit)'{-S+,--unit=}'[specify unit for displayed sizes]:unit prefix [K]:((k\:1000 K\:1024 m\:1000000 M\:1048576))' + '1: :_guard "[0-9]#" "interval (seconds)"' '2:count' + + '(action)' \ + '(- :)'{-h,--help}'[display help information]' + '(- :)'{-V,--version}'[display version information]' + {-a,--active}'[show active/inactive memory]' + '(- :)'{-f,--forks}'[show number of forks since boot]' + '(-S --unit -t --timestamp -w --wide)'{-m,--slabs}'[show slabinfo]' + '(-w --wide -n --one-header -t --timestamp :)'{-s,--stats}'[show event counter statistics]' + {-d,--disk}'[show disk statistics]' + {-p+,--partition=}'[show partition specific statistics]:partition:_files -W /dev -g "*(-%)"' + '(- :)'{-D,--disk-sum}'[summarize disk statistics]' ) ;; - freebsd*|openbsd*) + *bsd*) specs=( - '-c[number of times to refresh the display]:count' + '-c+[specify number of times to refresh the display]:count' '-f[report on the number fork syscalls since boot and pages of virtual memory for each]' '-i[report the number of interrupts taken by devices since boot]' - '-M[source file to extract values associated with the name list from]:core:_files' - '-N[source file to extract the name list from]:system:_files' - '-w[specify delay between each display]:delay (seconds)' + '-M+[specify core file to extract values associated with the name list from]:core:_files' + '-N+[specify file to extract the name list from]:system:_files' + '-w+[specify delay between each display]:delay (seconds)' '*:disk:_files' ) ;| @@ -35,23 +38,60 @@ case $OSTYPE in '-h[human readable memory columns output]' '-H[scriptable memory columns output]' '-m[report on the usage of kernel dynamic memory allocated using malloc(9) by type]' - '-n[change the maximum number of disks to display]:number of disks to display' + '-n+[change the maximum number of disks to display]:number of disks to display' '-o[list virtual memory objects]' '-P[report per-cpu system/user/idle cpu statistics]' - '-p[specify which types of devices to display]: :->devices' - '-s[display the contents of the SUM structure]:sum' + '-p+[specify which types of devices to display]: :->devices' + '-s[display the contents of the SUM structure]' '-z[report on memory used by the kernel zone allocator, uma(9), by zone]' ) - ;; - openbsd*) + ;| + (net|open)bsd*) specs+=( '-m[report usage of kernel dynamic memory listed first by size of allocation then type of usage]' - '-s[display the contents of the UVMEXP structure]:uvmexp' - '-t[report on the number of page in and page reclaims since boot]' + '-s[display the contents of the UVMEXP structure]' '-v[print more verbose information]' + ) + ;| + openbsd*) + specs+=( + '-t[report on the number of page in and page reclaims since boot]' '-z[include statistics about all interrupts]' ) ;; + netbsd*) + specs+=( + '-C[report on kernel memory caches]' + '-e[report the values of system event counters]' + '-H[report all hash table statistics]' + '-h+[dump specified hash table]:hash table:->hashes' + '-L[list all hash tables]' + '-l[list UVM histories maintained by the kernel]' + '-t[display contents of the vmtotal structure]' + '-U[dump all UVM histories]' + '-u+[dump specified UVM history]:uvm' + '-W[print more information about kernel memory pools]' + ) + ;; + freebsd*|solaris*) + specs+=( + '::disk:_files -W /dev -g "*(-%b)"' + ': :_guard "[0-9]#" "interval (seconds)"' ':count' + ) + ;| + solaris2.<11->) + specs+=( '(-i -s)-T+[specify time format]:time format:((u\:seconds\ since\ epoch d\:standard\ date\ format))' ) + ;& + solaris*) + specs+=( + '-q[suppress messages related to state changes]' + + '(actions)' \ + '(-T)-i[report the number of interrupts taken by devices since boot]' + '-p[report paging activity]' + '(-T)-s[display the total number of system events since boot]' + '-S[report on swapping rather than paging activity]' + ) + ;; esac if (( $#specs )); then @@ -73,7 +113,11 @@ if (( $#specs )); then 'SCSI[Small Computer System Interface devices]' 'other[any other device interface]' 'pass[passthrough devices]' ) - _values -C -s , 'device type' "$types[@]" && ret=0 + _values -s , 'device type' "$types[@]" && ret=0 + elif [[ $state == hashes ]]; then + local -a tables + tables=( ${${${(f)"$(_call_program hashes $words[1] -L)"}[2,-1]#?}/ ##/:} ) + _describe -t hashes 'hash table' tables && ret=0 fi return ret fi diff --git a/Completion/Unix/Command/_w b/Completion/Unix/Command/_w new file mode 100644 index 000000000..8fb4154c7 --- /dev/null +++ b/Completion/Unix/Command/_w @@ -0,0 +1,47 @@ +#compdef w + +local args + +case $OSTYPE in + linux*) + args=( + '(H -f --from)'{-f,--from}'[toggle display of remote hostname]' + '(H -h)--no-header[suppress the heading]' + '(H -i --ip-addr)'{-i,--ip-addr}'[display IP address instead of hostname]' + '(H -o --old-style -s --short)'{-o,--old-style}'[old style output format]' + '(H -s --short -o --old-style)'{-s,--short}'[use short output format]' + '(H -u --no-current)'{-u,--no-current}'[ignore the username while figuring out the current process and cpu times]' + + H + '(-)--help[display help information]' + '(-)'{-V,--version}'[display version information]' + ) + ;; + *bsd*|darwin*|dragonfly*) + args+=( '-i[sort output by idle time]' ) + ;| + openbsd*) + args+=( '-a[translate network addresses into names]' ) + ;| + (free|net)bsd*|dragonfly*) + args+=( '-n[show network addresses as numbers]' ) + ;| + *bsd*|dragonfly*) + args+=( + '-M+[extract values from specified core]:core file:_files' + '-N+[extract name list from specified system]:system file:_files' + ) + ;| + freebsd*|dragonfly*) + args+=( '-d[dump process list on a per controlling tty basis]' ) + ;| + solaris*) + args+=( '!(-s -w -l)'{-l,-w} + '-s[short output form]' + '(-)-u[produce only the heading line]' + ) + ;| +esac + +_arguments -S -s \ + '(--no-header)-h[suppress the heading]' \ + '*:user:_users' $args diff --git a/Completion/Unix/Command/_who b/Completion/Unix/Command/_who new file mode 100644 index 000000000..1f901af18 --- /dev/null +++ b/Completion/Unix/Command/_who @@ -0,0 +1,64 @@ +#compdef who gwho + +local args variant + +_pick_variant -r variant gnu=GNU $OSTYPE --version + +case $variant in + gnu) + args=( + '(Q -a --all -b --boot -d --dead -l --login -p --process -q --count -r --runlevel -t --time -T -w --mesg --message --writable -u --users)'{-a,--all}'[same as -b -d --login -p -r -t -T -u]' + '(Q -b --boot)'{-b,--boot}'[print time of last system boot]' + '(Q -d --dead -a --all)'{-d,--dead}'[print dead processes]' + '(Q -H --heading)'{-H,--heading}'[print line of column headings]' + '(Q -l --login)'{-l,--login}'[print system login processes]' + '(Q)--lookup[canonicalize hostnames via DNS]' + '(Q)-m[print information about current terminal]' + '(Q -p --process)'{-p,--process}'[print active processes spawned by init]' + '(Q -r --runlevel)'{-r,--runlevel}'[print current runlevel]' + '(Q -t --time)'{-t,--time}'[print last system clock change]' + '(Q -T -w --mesg --message --writable)'{-T,-w,--mesg,--message,--writable}"[show user's message acceptance status as +, - or ?]" + '(Q -u --users)'{-u,--users}'[show idle time]' + '!(Q -a)-s' '!(Q -a)--short' + + Q + '(-)'{-q,--count}'[print only login names and number of users logged on]' + '(-)--help[display help information]' + '(-)--version[display version information]' + ) + ;; + darwin*|dragonfly*|netbsd*|solaris*) + args=( + '(Q -a)-d[print dead processes]' + '(Q -a)-l[print system login processes]' + '(Q -a)-p[print active processes spawned by init]' + '(Q -a)-r[print current runlevel]' + '(Q -a)-t[print last system clock change]' + ) + ;| + dragonfly*|netbsd*) + args+=( '(Q)-v[show process exit status, session id etc]' ) + ;| + (net|free)bsd*|darwin*|dragonfly*|solaris*) + args+=( + '(Q -b -d -p -r -T -u)-a[print all entries]' + '(Q -a)-b[print time of last system boot]' + '!(Q -a)-s' + ) + ;| + *) + args+=( + '(Q)-H[print line of column headings]' + '(Q)-m[print information about current terminal]' + "(Q -a)-T[show user's message acceptance status as +, - or ?]" + '(Q -a)-u[show idle time]' + + Q '(-a -b -d -H -l -m -p -r -s -t -T -v)-q[print only login names and number of users logged on]' + ) + ;| + solaris*) + args+=( + '(-a -b -d -H -l -m -p -r -s -t -T)-n+[specify number of users to list per line]:number' + ) + ;; +esac + +_arguments -s -S ':file:_files' $args diff --git a/Completion/Unix/Type/_bpf_filters b/Completion/Unix/Type/_bpf_filters new file mode 100644 index 000000000..c62481e09 --- /dev/null +++ b/Completion/Unix/Type/_bpf_filters @@ -0,0 +1,215 @@ +# spaces are valid instead of word ends, perhaps better to just do compset -q + +local -a networks fields dirs protos relop +local -A subtypes flags +local values dir wlantype skip repeat=1 packet proto=0 +local suf=']' + +local WORD=$'[^ \0]##[ \0]##' + +networks=( + /$'[^/ \0]#'/ + \( + /$'[ \0]'/ ': _message -e networks network' + /$'mask[ \0]'/ ':masks:mask:(mask)' + /$WORD/ ':netmasks:netmask:' + \| + /// /$WORD/ ': _message -e masks "netmask length (bits)"' + \) +) +subtypes=( + mgt 'assoc-req assoc-resp reassoc-req reassoc-resp probe-req probe-resp beacon atim disassoc auth deauth' + ctl 'ps-poll rts cts ack cf-end cf-end-ack' + data 'data data-cf-ack data-cf-poll data-cf-ack-poll null cf-ack cf-poll cf-ack-poll qos-data qos-data-cf-ack qos-data-cf-poll qos-data-cf-ack-poll qos qos-cf-poll and qos-cf-ack-poll' +) +flags=( + len len + tcp 'tcp-fin tcp-syn tcp-rst tcp-push tcp-ack tcp-urg' + icmp 'icmp-echoreply icmp-unreach icmp-sourcequench icmp-redirect icmp-echo icmp-routeradvert icmp-routersolicit icmp-timxceed icmp-paramprob icmp-tstamp icmp-tstampreply icmp-ireq icmp-ireqreply icmp-maskreq icmp-maskreply' +) + +case $OSTYPE in + solaris*) + fields=( ipaddr etheraddr atalkaddr ethertype rpc nofrag inet inet6 vlan-id ) + protos=( bootp dhcp dhcp6 apple pppoe ldap slp ospf ) + dirs=( from to ) + relop=( \^ % ) + ;| + solaris2.<11->) + fields+=( zone ) + ;| + (free|open)bsd*) # pf(4) specific filters + fields=( ifname on rnr rulenum srnr subruleset reason ruleset rset action ) + ;| + ^(solaris|openbsd)*) + protos+=( mpls netbeui iso geneve aarp ipx llc ) + ;| + ^openbsd*) + protos+=( ah esp sctp pppoed pppoes ) + ;| + ^solaris*) + protos+=( fddi wlan atalk stp lat moprc mopdl ) + relop=( '>>' '<<' ) + ;; +esac + +compquote suf + +# the regex is essentially: +# ( [not]* ( expression | [protocol]? [standalone-field | direction field ]? ) and|or ) * +# the proto variable ensures that and/or is not allowed if there is no +# protocol or field: it is one, the other or both but not neither + +_regex_arguments _bpf /$'[^\0]#\0'/ \( \ + /$'(not[ \0]#|![ \0]#|(\\\\|)\\([ \0]#)'/ ':operators:operator:(not ()' \# \ + \(\ + \(\ + \(\ + /"(0x[0-9a-f]##|[0-9]##|${(j.|.)${=flags}})"$'[ \0]#'/ -'((repeat != 2))' ":expressions:expression:compadd ${=flags[$packet]}" \ + \|\ + /'[a-z]##(\\|)\[[^\]]##(\\|)\]'$'[ \0]#'/ \ + \|\ + /'[a-z]##(\\|)\[[^:\]]##:'/ /'[]'/ ':sizes:field size (bytes):compadd -S "$suf" 1 2 4' \ + \|\ + /'tcp(\\|)\['/ -packet=tcp \ + /'[]'/ ':offsets:header offset:compadd -S "$suf " tcpflags' \ + \|\ + /'icmp(\\|)\['/ -packet=icmp \ + /'[]'/ ':offsets:header offset:compadd -S "$suf " icmptype icmpcode' \ + \|\ + /'[a-z]##(\\|)\['/ /'[]'/ ':offsets:offset:' \ + \)\ + \(\ + /$'(\\\\|)([<>=!](\\\\|)[<>=]|[<>&|=+*/%^-])[ \0]#'/ -'repeat=0' ":operators:operator:(+ - = != < > <= >= & | $relop and or)" \ + // ': _message -e expressions expression' \ + \|\ + // -'repeat=2' \ + \)\ + \) \# \ + // -'(( repeat == 2))' \ + // -'repeat=1' \ + \|\ + /$'ether[ \0]proto[ \0]'/ \ + /$WORD/ ':protocols:protocol:(\ip \ip6 \arp \rarp \atalk \aarp \dec \net \sca \lat \mopdl \moprc \iso \stp \ipx \netbeui)' \ + \|\ + /$'(less|greater)[ \0]'/ ':fields:field:(less greater)' \ + /$WORD/ ':numbers:length (bytes):' \ + \|\ + \(\ + /$'(tcp|udp|icmp|ether|ip|ip6|arp|rarp|decnet|bootp|dhcp|dhcp6|apple|pppoe|pppoed|ldap|ah|esp|slp|sctp|ospf|iso|clnp|esis|isis|atalk|aarp|iso|stp|ipx|netbeui|lat|moprc|mopdl)[ \0]'/ ":protocols:protocol qualifier:(tcp udp icmp ether tr ip ip6 arp rarp decnet $protos)" \ + \| /$'((fddi|tr|wlan)[ \0]|)'/ '-(( ++proto ))' \) \ + \(\ + /$'mpls[ \0]'/ \ + /$'((0x|)[0-9a-f]##[ \0]|)'/ ': _message -e labels "label number"' \ + \|\ + /$'geneve[ \0]'/ \ + /$'((0x|)[0-9a-f]##[ \0]|)'/ ': _message -e vnis "vni"' \ + \|\ + /$'pppoes[ \0]'/ \ + /$'((0x|)[0-9a-f]##[ \0]|)'/ ': _message -e session-ids "session id"' \ + \|\ + /$'proto[ \0]'/ ':fields:field:(proto)' \ + /$WORD/ ':protocols:protocol:(\icmp \icmp6 \igmp \igrp \pim \ah \esp \vrrp \udp \tcp)' \ + \|\ + /$'(broad|multi)cast[ \0]'/ ':fields:field:(broadcast multicast)' \ + \|\ + /$'type[ \0]'/ ':fields:field:(type)' \ + /$WORD/ -'wlantype=${match%?}' ':wlan-types:wlan type:(mgt ctl data)' \ + \(\ + /$'subtype[ \0]'/ ':fields:field:(subtype)' \ + /$WORD/ ':subtypes:subtype:compadd ${=subtypes[$wlantype]:-$subtypes}' \ + \| \)\ + \|\ + /$'protochain[ \0]'/ ':fields:field:(protochain)' \ + /$WORD/ ':protocols:protocol:' \ + \|\ + /$'vlan-id[ \0]'/ \ + /$WORD/ ':vlans:vlan:' \ + \|\ + /$'vlan[ \0]'/ ':fields:field:(vlan)' \ + \( /$WORD/ ': _message -e vlans vlan' \| \) \ + \|\ + \(\ + /$'(ra|ta|addr[1-4]|inbound|outbound)[ \0]'/ ":directions:direction qualifier:(src dst inbound outbound ra ta addr1 addr2 addr3 addr4 $dirs)" \ + \|\ + /$'(src|from|dst|to)[ \0]'/ -'values=${values:-hosts};dir=$match' \ + \(\ + /$'(or|and)[ \0]'/ ':operators:operator:(or and)' \ + /$'(src|dst)[ \0]'/ ':directions:direction qualifier:compadd ${${${${dir%?}:/dst/to}:/(src|from)/dst}:/to/src}' \ + \| \)\ + \| \)\ + \(\ + /$'(host|gateway)[ \0]'/ ":fields:field:(host gateway $fields)" \ + /$WORD/ -values=hosts ':hosts:host:_hosts' \ + \|\ + /$'inet(6|)[ \0]'/ \ + \( /$'host[ \0]'/ ':fields:field:(host)' \| \) \ + /$WORD/ -values=hosts ':hosts:host:_hosts' \ + \|\ + /$'ethertype[ \0]'/ \ + /$WORD/ ':numbers:number:' \ + \|\ + /$'(ipaddr|etheraddr|atalkaddr)[ \0]'/ \ + /$WORD/ ':addresses:address:' \ + \|\ + /$'llc[ \0]'/\ + /$'((s|u|rr|rnr|rej|ui|ua|disc|sabme|test|xid|frmr)[ \0]|)'/ ':types:type:(s u rr rnr rej ui ua disc sabme test xid frmr)' \ + \|\ + /$'(ifname|on)[ \0]'/ \ + /$WORD/ ':interfaces:interface:_net_interfaces' \ + \|\ + /$'(rnr|rulenum|srnr|subruleset)[ \0]'/ \ + /$WORD/ ':rules:rule number:' \ + \|\ + /$'reason[ \0]'/ \ + /$WORD/ ':reasons:reason:(match bad-offset fragment short normalize memory)' \ + \|\ + /$'(rset|ruleset)[ \0]'/ \ + /$WORD/ ':rule-sets:rule set:' \ + \|\ + /$'action[ \0]'/ \ + /$WORD/ ':actions:action:(pass block nat rdr binat scrub)' \ + \|\ + /$'rpc[ \0]'/ \ + \(\ + /$'[^, \0]##[ \0]'/ ':programs:rpc program:compadd -qS, - ${${(f)"$(</etc/rpc)"}%%[[:blank:]#]*}' \ + \|\ + /$'[^, \0]##,[^, \0]##,'/ /$'[^, \0]##[ \0]'/ ':procedures:procedure:' \ + \|\ + /$'[^, \0]##,'/ /$'[^, \0]##[ \0]'/ ':versions:version:' \ + \)\ + \|\ + /$'zone[ \0]'/ \ + /$WORD/ ':zones:zone:_zones' \ + \|\ + /$'port[ \0]'/ ':fields:field:(port)' \ + /$WORD/ -values=ports ':ports:port:_ports' \ + \|\ + /$'portrange[ \0]'/ -values=portranges ':fields:field:(portrange)' \ + /$'[^ \0-]##-'/ ':ports:port:_ports -S-' \ + /$WORD/ ':ports:port:_ports' \ + \|\ + /$'net[ \0]'/ -values='networks' ':fields:field:(net)' \ + $networks \ + \|\ + // -'[[ $values = hosts ]]' \ + /$WORD/ ':hosts:host:_hosts' \ + \|\ + // -'[[ $values = ports ]]' \ + /$WORD/ ':ports:port:_ports' \ + \|\ + // -'[[ $values = networks ]]' \ + $networks \ + \|\ + // -'[[ $values = portranges ]]' \ + /$'[^ \0-]##-'/ ':ports:port:_ports -S-' \ + /$WORD/ ':ports:port:_ports' \ + \|\ + // -'(( ++proto ))' \ + \)\ + \)\ + \)\ + // -'(( proto < 2 ))' \ + /$'(and|or|&&|\\|\\||\\))[ \0]'/ -proto=0 ':operators:operator:compadd and or \)' \) \# + +_bpf "$@" diff --git a/Config/version.mk b/Config/version.mk index 363618aca..9ec6475eb 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -27,5 +27,5 @@ # This must also serve as a shell script, so do not add spaces around the # `=' signs. -VERSION=5.4.1 -VERSION_DATE='August 8, 2017' +VERSION=5.4.2 +VERSION_DATE='August 27, 2017' diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 70092d681..42571fccd 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1659,6 +1659,13 @@ as it is by default, and the option tt(ERR_EXIT) is found to have been set on exit, then the command for which the tt(DEBUG) trap is being executed is skipped. The option is restored after the trap exits. +Non-zero status in a command list containing tt(&&) or tt(||) is ignored +for commands not at the end of the list. Hence + +example(false && true) + +does not trigger exit. + Exiting due to tt(ERR_EXIT) has certain interactions with asynchronous jobs noted in ifzman(the section JOBS in zmanref(zshmisc))\ @@ -1672,10 +1679,25 @@ cindex(function return, on error) cindex(return from function, on error) item(tt(ERR_RETURN))( If a command has a non-zero exit status, return immediately from the -enclosing function. The logic is identical to that for tt(ERR_EXIT), +enclosing function. The logic is similar to that for tt(ERR_EXIT), except that an implicit tt(return) statement is executed instead of an tt(exit). This will trigger an exit at the outermost level of a non-interactive script. + +Normally this option inherits the behaviour of tt(ERR_EXIT) that +code followed by `tt(&&)' `tt(||)' does not trigger a return. Hence +in the following: + +example(summit || true) + +no return is forced as the combined effect always has a zero return +status. + +Note. however, that if tt(summit) in the above example is itself a +function, code inside it is considered separately: it may force a return +from tt(summit) (assuming the option remains set within tt(summit)), but +not from the enclosing context. This behaviour is different from +tt(ERR_EXIT) which is unaffected by function scope. ) pindex(EVAL_LINENO) pindex(NO_EVAL_LINENO) diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index 689b90022..adde2d56c 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -306,7 +306,7 @@ sect(On what machines will it run?) sect(What's the latest version?) - Zsh 5.4.1 is the latest production version. For details of all the + Zsh 5.4.2 is the latest production version. For details of all the changes, see the NEWS file in the source distribution. A beta of the next version is sometimes available. Development of zsh is diff --git a/Functions/VCS_Info/VCS_INFO_patch2subject b/Functions/VCS_Info/VCS_INFO_patch2subject index e222e8382..a48c16b04 100644 --- a/Functions/VCS_Info/VCS_INFO_patch2subject +++ b/Functions/VCS_Info/VCS_INFO_patch2subject @@ -6,14 +6,18 @@ integer -r LIMIT=10 local -a lines local needle + readonly svn_log_pattern='^r[0-9]* [|] .*' if [[ -f "$1" ]]; then # Extract the first LIMIT lines, or up to the first empty line or the start of the unidiffs, # whichever comes first. while (( i++ < LIMIT )); do IFS= read -r "lines[$i]" - if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---|Index:)* ]]; then + if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---[^-]|Index:)* ]]; then lines[$i]=() - break + # For 'svn log -r N --diff' output, read the first paragraph too. + if ! [[ $lines[i-1] =~ $svn_log_pattern ]]; then + break + fi fi done < "$1" @@ -51,6 +55,9 @@ fi } < "$1" REPLY=$needle + elif [[ $lines[2] =~ $svn_log_pattern ]]; then + REPLY=$lines[4] + if (( ${+lines[5]} )); then REPLY+='...'; fi elif (( ${+lines[1]} )); then # The first line of the file is not part of the diff. REPLY=${lines[1]} @@ -5,11 +5,11 @@ THE Z SHELL (ZSH) Version ------- -This is version 5.4,1 of the shell. This is a stable release. There -are a few visible improvements since 5.3.1, the last widely released -version, as well as many bugfixes. Note in particular the changs -highlighted under "Incompatibilites since 5.3.1" below. See NEWS for -more information. +This is version 5.4.2 of the shell. This is a stable release. There +are some significant bug fixes over 5.4.1 and a few visible improvements +since 5.3.1, the previous widely released version, as well as many +bug fixes. Note in particular the changs highlighted under +"Incompatibilites since 5.3.1" below. See NEWS for more information. Installing Zsh -------------- @@ -81,6 +81,19 @@ against user defined widgets inadvertently reading from the tty device, and addresses the antisocial behaviour of running a command with its stdin closed. +5) [New between 5.4.1 and 5.4.2] In previous versions of the shell, the +following code: + + () { setopt err_return; false; echo 'oh no' } && true + +printed "oh no", as the ERR_RETURN behaviour was suppressed when +a function was executed on the left hand side of an "&&" list. This was +undocumented and inconvenient as it is generally more useful to consider +execution within a function in isolation from its environment. The shell +now returns from the function on executing `false'. (This is general +to all functions; an anonymous function is shown here for compactness.) + + Incompatibilities between 5.0.8 and 5.3 ---------------------------------------- diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c index 27191d709..659fd22d5 100644 --- a/Src/Modules/pcre.c +++ b/Src/Modules/pcre.c @@ -148,7 +148,7 @@ bin_pcre_study(char *nam, UNUSED(char **args), UNUSED(Options ops), UNUSED(int f /**/ static int -zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, +zpcre_get_substrings(char *arg, int *ovec, int captured_count, char *matchvar, char *substravar, int want_offset_pair, int matchedinarr, int want_begin_end) { @@ -156,15 +156,13 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, char offset_all[50]; int capture_start = 1; - if (matchedinarr) + if (matchedinarr) { + /* bash-style captures[0] entire-matched string in the array */ capture_start = 0; - if (matchvar == NULL) - matchvar = "MATCH"; - if (substravar == NULL) - substravar = "match"; - + } + /* captures[0] will be entire matched string, [1] first substring */ - if (!pcre_get_substring_list(arg, ovec, ret, (const char ***)&captures)) { + if (!pcre_get_substring_list(arg, ovec, captured_count, (const char ***)&captures)) { int nelem = arrlen(captures)-1; /* Set to the offsets of the complete match */ if (want_offset_pair) { @@ -176,30 +174,43 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, * difference between the two values in each paired entry in ovec. * ovec is length 2*(1+capture_list_length) */ - match_all = metafy(captures[0], ovec[1] - ovec[0], META_DUP); - setsparam(matchvar, match_all); + if (matchvar) { + match_all = metafy(captures[0], ovec[1] - ovec[0], META_DUP); + setsparam(matchvar, match_all); + } /* * If we're setting match, mbegin, mend we only do * so if there were parenthesised matches, for consistency - * (c.f. regex.c). + * (c.f. regex.c). That's the next block after this one. + * Here we handle the simpler case where we don't worry about + * Unicode lengths, etc. + * Either !want_begin_end (ie, this is bash) or nelem; if bash + * then we're invoked always, even without nelem results, to + * set the array variable with one element in it, the complete match. */ - if (!want_begin_end || nelem) { + if (substravar && + (!want_begin_end || nelem)) { char **x, **y; - int vec_off; + int vec_off, i; y = &captures[capture_start]; - matches = x = (char **) zalloc(sizeof(char *) * (arrlen(y) + 1)); - vec_off = 2; - do { + matches = x = (char **) zalloc(sizeof(char *) * (captured_count+1-capture_start)); + for (i = capture_start; i < captured_count; i++, y++) { + vec_off = 2*i; if (*y) *x++ = metafy(*y, ovec[vec_off+1]-ovec[vec_off], META_DUP); else *x++ = NULL; - vec_off += 2; - } while (*y++); + } + *x = NULL; setaparam(substravar, matches); } if (want_begin_end) { + /* + * cond-infix rather than builtin; also not bash; so we set a bunch + * of variables and arrays to values which require handling Unicode + * lengths + */ char *ptr = arg; zlong offs = 0; int clen, leftlen; @@ -306,7 +317,9 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) zwarnnam(nam, "no pattern has been compiled"); return 1; } - + + matched_portion = "MATCH"; + receptacle = "match"; if(OPT_HASARG(ops,c='a')) { receptacle = OPT_ARG(ops,c); } @@ -318,8 +331,8 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } /* For the entire match, 'Return' the offset byte positions instead of the matched string */ - if(OPT_ISSET(ops,'b')) want_offset_pair = 1; - + if(OPT_ISSET(ops,'b')) want_offset_pair = 1; + if ((ret = pcre_fullinfo(pcre_pattern, pcre_hints, PCRE_INFO_CAPTURECOUNT, &capcount))) { zwarnnam(nam, "error %d in fullinfo", ret); @@ -360,7 +373,7 @@ cond_pcre_match(char **a, int id) { pcre *pcre_pat; const char *pcre_err; - char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar=NULL; + char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar, *svar; int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize; int lhstr_plain_len, rhre_plain_len; int return_value = 0; @@ -380,8 +393,13 @@ cond_pcre_match(char **a, int id) ov = NULL; ovsize = 0; - if (isset(BASHREMATCH)) - avar="BASH_REMATCH"; + if (isset(BASHREMATCH)) { + svar = NULL; + avar = "BASH_REMATCH"; + } else { + svar = "MATCH"; + avar = "match"; + } switch(id) { case CPCRE_PLAIN: @@ -414,7 +432,7 @@ cond_pcre_match(char **a, int id) break; } else if (r>0) { - zpcre_get_substrings(lhstr_plain, ov, r, NULL, avar, 0, + zpcre_get_substrings(lhstr_plain, ov, r, svar, avar, 0, isset(BASHREMATCH), !isset(BASHREMATCH)); return_value = 1; diff --git a/Src/exec.c b/Src/exec.c index f339dd6d0..cd99733f1 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -41,12 +41,15 @@ enum { ADDVAR_RESTORE = 1 << 2 }; -/* used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT. */ +/* + * used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT. + * Bits from noerrexit_bits. + */ /**/ int noerrexit; -/* used to suppress ERREXIT for one occurrence */ +/* used to suppress ERREXIT or ERRRETURN for one occurrence: 0 or 1 */ /**/ int this_noerrexit; @@ -972,7 +975,7 @@ enum { static void entersubsh(int flags) { - int sig, monitor, job_control_ok; + int i, sig, monitor, job_control_ok; if (!(flags & ESUB_KEEPTRAP)) for (sig = 0; sig < SIGCOUNT; sig++) @@ -1083,6 +1086,14 @@ entersubsh(int flags) opts[MONITOR] = 0; opts[USEZLE] = 0; zleactive = 0; + /* + * If we've saved fd's for later restoring, we're never going + * to restore them now, so just close them. + */ + for (i = 10; i <= max_zsh_fd; i++) { + if (fdtable[i] & FDT_SAVED_MASK) + zclose(i); + } if (flags & ESUB_PGRP) clearjobtab(monitor); get_usage(); @@ -1291,7 +1302,7 @@ execlist(Estate state, int dont_change_job, int exiting) int oerrexit_opt = opts[ERREXIT]; Param pm; opts[ERREXIT] = 0; - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; if (ltype & Z_SIMPLE) /* skip the line number */ pc2++; pm = setsparam("ZSH_DEBUG_CMD", getpermtext(state->prog, pc2, 0)); @@ -1343,13 +1354,13 @@ execlist(Estate state, int dont_change_job, int exiting) int isend = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END); next = state->pc + WC_SUBLIST_SKIP(code); if (!oldnoerrexit) - noerrexit = !isend; + noerrexit = isend ? 0 : NOERREXIT_EXIT | NOERREXIT_RETURN; if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) { /* suppress errexit for "! this_command" */ if (isend) this_noerrexit = 1; /* suppress errexit for ! <list-of-shell-commands> */ - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; } switch (WC_SUBLIST_TYPE(code)) { case WC_SUBLIST_END: @@ -1436,11 +1447,11 @@ sublist_done: /* * See hairy code near the end of execif() for the - * following. "noerrexit == 2" only applies until + * following. "noerrexit " only applies until * we hit execcmd on the way down. We're now * on the way back up, so don't restore it. */ - if (oldnoerrexit != 2) + if (!(oldnoerrexit & NOERREXIT_UNTIL_EXEC)) noerrexit = oldnoerrexit; if (sigtrapped[SIGDEBUG] && !isset(DEBUGBEFORECMD) && !donedebug) { @@ -1450,7 +1461,7 @@ sublist_done: */ int oerrexit_opt = opts[ERREXIT]; opts[ERREXIT] = 0; - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; exiting = donetrap; ret = lastval; dotrap(SIGDEBUG); @@ -1466,16 +1477,19 @@ sublist_done: /* Check whether we are suppressing traps/errexit * * (typically in init scripts) and if we haven't * * already performed them for this sublist. */ - if (!noerrexit && !this_noerrexit && !donetrap && !this_donetrap) { - if (sigtrapped[SIGZERR] && lastval) { + if (!this_noerrexit && !donetrap && !this_donetrap) { + if (sigtrapped[SIGZERR] && lastval && + !(noerrexit & NOERREXIT_EXIT)) { dotrap(SIGZERR); donetrap = 1; } if (lastval) { int errreturn = isset(ERRRETURN) && - (isset(INTERACTIVE) || locallevel || sourcelevel); - int errexit = isset(ERREXIT) || - (isset(ERRRETURN) && !errreturn); + (isset(INTERACTIVE) || locallevel || sourcelevel) && + !(noerrexit & NOERREXIT_RETURN); + int errexit = (isset(ERREXIT) || + (isset(ERRRETURN) && !errreturn)) && + !(noerrexit & NOERREXIT_EXIT); if (errexit) { if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); @@ -2318,6 +2332,9 @@ addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag, return; } save[fd1] = fdN; + DPUTS(fdtable[fdN] != FDT_INTERNAL, + "Saved file descriptor not marked as internal"); + fdtable[fdN] |= FDT_SAVED_MASK; } } } @@ -3008,7 +3025,7 @@ execcmd_exec(Estate state, Execcmd_params eparams, preargs = NULL; /* if we get this far, it is OK to pay attention to lastval again */ - if (noerrexit == 2 && !is_shfunc) + if ((noerrexit & NOERREXIT_UNTIL_EXEC) && !is_shfunc) noerrexit = 0; /* Do prefork substitutions. @@ -3575,7 +3592,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, } if (!bad && fn->fd1 <= max_zsh_fd) { if (fn->fd1 >= 10 && - fdtable[fn->fd1] == FDT_INTERNAL) + (fdtable[fn->fd1] & FDT_TYPE_MASK) == + FDT_INTERNAL) bad = 3; } } @@ -4270,7 +4288,7 @@ closem(int how) for (i = 10; i <= max_zsh_fd; i++) if (fdtable[i] != FDT_UNUSED && - (how == FDT_UNUSED || fdtable[i] == how)) { + (how == FDT_UNUSED || (fdtable[i] & FDT_TYPE_MASK) == how)) { if (i == SHTTY) SHTTY = -1; zclose(i); @@ -5450,6 +5468,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) char saveopts[OPT_SIZE], *oldscriptname = scriptname; char *name = shfunc->node.nam; int flags = shfunc->node.flags, ooflags; + int savnoerrexit; char *fname = dupstring(name); int obreaks, ocontflag, oloops, saveemulation, restore_sticky; Eprog prog; @@ -5472,6 +5491,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) trap_return--; oldlastval = lastval; oldnumpipestats = numpipestats; + savnoerrexit = noerrexit; + /* + * Suppression of ERR_RETURN is turned off in function scope. + */ + noerrexit &= ~NOERREXIT_RETURN; if (noreturnval) { /* * Easiest to use the heap here since we're bracketed @@ -5690,6 +5714,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) if (trap_state == TRAP_STATE_PRIMED) trap_return++; ret = lastval; + noerrexit = savnoerrexit; if (noreturnval) { lastval = oldlastval; numpipestats = oldnumpipestats; diff --git a/Src/init.c b/Src/init.c index d8c26aca2..87dd2e26d 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1070,7 +1070,7 @@ setupvals(char *cmd, char *runscript, char *zsh_name) sfcontext = SFC_NONE; trap_return = 0; trap_state = TRAP_STATE_INACTIVE; - noerrexit = -1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL; nohistsave = 1; dirstack = znewlinklist(); bufstack = znewlinklist(); @@ -1199,7 +1199,7 @@ init_signals(void) void run_init_scripts(void) { - noerrexit = -1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL; if (EMULATION(EMULATE_KSH|EMULATE_SH)) { if (islogin) @@ -760,7 +760,7 @@ gettok(void) return AMPER; case LX1_BAR: d = hgetc(); - if (d == '|') + if (d == '|' && !incasepat) return DBAR; else if (d == '&') return BARAMP; @@ -1058,7 +1058,7 @@ gettokstr(int c, int sub) if (isset(SHGLOB)) { if (sub || in_brace_param) break; - if (incasepat && !lexbuf.len) + if (incasepat > 0 && !lexbuf.len) return INPAR; if (!isset(KSHGLOB) && lexbuf.len) goto brk; @@ -1859,7 +1859,7 @@ exalias(void) Reswd rw; hwend(); - if (interact && isset(SHINSTDIN) && !strin && !incasepat && + if (interact && isset(SHINSTDIN) && !strin && incasepat <= 0 && tok == STRING && !nocorrect && !(inbufflags & INP_ALIAS) && (isset(CORRECTALL) || (isset(CORRECT) && incmdpos))) spckword(&tokstr, 1, incmdpos, 1); diff --git a/Src/loop.c b/Src/loop.c index f7eae307b..4859c976b 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -542,7 +542,7 @@ execif(Estate state, int do_exec) end = state->pc + WC_IF_SKIP(code); if (!noerrexit) - noerrexit = 1; + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN; while (state->pc < end) { code = *state->pc++; if (wc_code(code) != WC_IF || @@ -567,7 +567,12 @@ execif(Estate state, int do_exec) if (run) { /* we need to ignore lastval until we reach execcmd() */ - noerrexit = olderrexit ? olderrexit : lastval ? 2 : 0; + if (olderrexit) + noerrexit = olderrexit; + else if (lastval) + noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_UNTIL_EXEC; + else + noerrexit = 0; cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN)); execlist(state, 1, do_exec); cmdpop(); diff --git a/Src/module.c b/Src/module.c index 21d68b1ac..4ae78310f 100644 --- a/Src/module.c +++ b/Src/module.c @@ -649,11 +649,21 @@ getconddef(int inf, const char *name, int autol) { Conddef p; int f = 1; + char *lookup, *s; + + /* detokenize the Dash to the form encoded in lookup tables */ + lookup = dupstring(name); + if (!lookup) + return NULL; + for (s = lookup; *s != '\0'; s++) { + if (*s == Dash) + *s = '-'; + } do { for (p = condtab; p; p = p->next) { if ((!!inf == !!(p->flags & CONDF_INFIX)) && - !strcmp(name, p->name)) + !strcmp(lookup, p->name)) break; } if (autol && p && p->module) { @@ -664,7 +674,7 @@ getconddef(int inf, const char *name, int autol) if (f) { (void)ensurefeature(p->module, (p->flags & CONDF_INFIX) ? "C:" : "c:", - (p->flags & CONDF_AUTOALL) ? NULL : name); + (p->flags & CONDF_AUTOALL) ? NULL : lookup); f = 0; p = NULL; } else { @@ -674,6 +684,7 @@ getconddef(int inf, const char *name, int autol) } else break; } while (!p); + return p; } diff --git a/Src/parse.c b/Src/parse.c index ba9cd61eb..27052527d 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -48,7 +48,11 @@ mod_export int incond; /**/ mod_export int inredir; -/* != 0 if we are about to read a case pattern */ +/* + * 1 if we are about to read a case pattern + * -1 if we are not quite sure + * 0 otherwise + */ /**/ int incasepat; @@ -1194,6 +1198,7 @@ par_case(int *cmplx) for (;;) { char *str; + int skip_zshlex; while (tok == SEPER) zshlex(); @@ -1201,11 +1206,17 @@ par_case(int *cmplx) break; if (tok == INPAR) zshlex(); - if (tok != STRING) - YYERRORV(oecused); - if (!strcmp(tokstr, "esac")) - break; - str = dupstring(tokstr); + if (tok == BAR) { + str = dupstring(""); + skip_zshlex = 1; + } else { + if (tok != STRING) + YYERRORV(oecused); + if (!strcmp(tokstr, "esac")) + break; + str = dupstring(tokstr); + skip_zshlex = 0; + } type = WC_CASE_OR; pp = ecadd(0); palts = ecadd(0); @@ -1243,10 +1254,11 @@ par_case(int *cmplx) * this doesn't affect our ability to match a | or ) as * these are valid on command lines. */ - incasepat = 0; + incasepat = -1; incmdpos = 1; - for (;;) { + if (!skip_zshlex) zshlex(); + for (;;) { if (tok == OUTPAR) { ecstr(str); ecadd(ecnpats++); @@ -1302,10 +1314,26 @@ par_case(int *cmplx) } zshlex(); - if (tok != STRING) + switch (tok) { + case STRING: + /* Normal case */ + str = dupstring(tokstr); + zshlex(); + break; + + case OUTPAR: + case BAR: + /* Empty string */ + str = dupstring(""); + break; + + default: + /* Oops. */ YYERRORV(oecused); - str = dupstring(tokstr); + break; + } } + incasepat = 0; par_save_list(cmplx); if (tok == SEMIAMP) type = WC_CASE_AND; diff --git a/Src/signals.c b/Src/signals.c index cad40f4eb..94f379e72 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -652,7 +652,7 @@ zhandler(int sig) case SIGINT: if (!handletrap(SIGINT)) { if ((isset(PRIVILEGED) || isset(RESTRICTED)) && - isset(INTERACTIVE) && noerrexit < 0) + isset(INTERACTIVE) && (noerrexit & NOERREXIT_SIGNAL)) zexit(SIGINT, 1); if (list_pipe || chline || simple_pline) { breaks = loops; @@ -456,6 +456,18 @@ enum { #define FDT_PROC_SUBST 7 #endif +/* + * Mask to get the basic FDT type. + */ +#define FDT_TYPE_MASK 15 + +/* + * Bit flag that fd is saved for later restoration. + * Currently this is only use with FDT_INTERNAL. We use this fact so as + * not to have to mask checks against other types. + */ +#define FDT_SAVED_MASK 16 + /* Flags for input stack */ #define INP_FREE (1<<0) /* current buffer can be free'd */ #define INP_ALIAS (1<<1) /* expanding alias or history */ @@ -2110,6 +2122,17 @@ enum source_return { SOURCE_ERROR = 2 }; +enum noerrexit_bits { + /* Suppress ERR_EXIT and traps: global */ + NOERREXIT_EXIT = 1, + /* Suppress ERR_RETURN: per function call */ + NOERREXIT_RETURN = 2, + /* NOERREXIT only needed on way down */ + NOERREXIT_UNTIL_EXEC = 4, + /* Force exit on SIGINT */ + NOERREXIT_SIGNAL = 8 +}; + /***********************************/ /* Definitions for history control */ /***********************************/ diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst index 9625a15bc..0302c9624 100644 --- a/Test/A01grammar.ztst +++ b/Test/A01grammar.ztst @@ -820,6 +820,43 @@ 0:case keeps exit status of last command executed in compound-list >37 + case '' in + burble) print No. + ;; + spurble|) print Yes! + ;; + |burble) print Not quite. + ;; + esac + case '' in + burble) print No. + ;; + |burble) print Wow! + ;; + spurble|) print Sorry. + ;; + esac + case '' in + gurgle) print No. + ;; + wurgle||jurgle) print Yikes! + ;; + durgle|) print Hmm. + ;; + |zurgle) print Hah. + ;; + esac + case '' in + # Useless doubled empty string to check special case. + ||jurgle) print Ok. + ;; + esac +0: case with no opening parentheses and empty string +>Yes! +>Wow! +>Yikes! +>Ok. + x=1 x=2 | echo $x echo $x diff --git a/Test/E01options.ztst b/Test/E01options.ztst index f01d83567..8101ff539 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -345,6 +345,36 @@ >ZERR trapped >off after + ( + setopt ERR_EXIT + () { false; print is executed; } && true + () { false; print is not executed; } + print is not executed + ) +1:ERR_EXIT is suppressed within a function followed by "&&" +>is executed + + ( + setopt ERR_RETURN + () { false; print is not executed; } || print is executed + print is also executed + ) +0:ERR_RETURN is not suppressed within a function followed by "||" +>is executed +>is also executed + + ( + setopt ERR_RETURN + () { + () { false; print Not executed 1; } || true + print Executed + () { false; print Not executed 2; } + print Not executed 3; + } && false + ) +1:ERR_RETURN with additional levels +>Executed + (print before; setopt noexec; print after) 0:NO_EXEC option >before diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst index 7426e7bf8..9feeb47fb 100644 --- a/Test/V07pcre.ztst +++ b/Test/V07pcre.ztst @@ -137,6 +137,39 @@ 0:ensure ASCII NUL passes in and out of matched plaintext >6; 3; 3 +# Ensure the long-form infix operator works + [[ foo -pcre-match ^f..$ ]] + print $? + [[ foo -pcre-match ^g..$ ]] + print $? + [[ ! foo -pcre-match ^g..$ ]] + print $? +0:infix -pcre-match works +>0 +>1 +>0 + +# Bash mode; note zsh documents that variables not updated on match failure, +# which remains different from bash + setopt bash_rematch + [[ "goo" -pcre-match ^f.+$ ]] ; print $? + [[ "foo" -pcre-match ^f.+$ ]] ; print -l $? _${^BASH_REMATCH[@]} + [[ "foot" -pcre-match ^f([aeiou]+)(.)$ ]]; print -l $? _${^BASH_REMATCH[@]} + [[ "foo" -pcre-match ^f.+$ ]] ; print -l $? _${^BASH_REMATCH[@]} + [[ ! "goo" -pcre-match ^f.+$ ]] ; print $? + unsetopt bash_rematch +0:bash-compatibility works +>1 +>0 +>_foo +>0 +>_foot +>_oo +>_t +>0 +>_foo +>0 + # Subshell because crash on failure ( setopt re_match_pcre [[ test.txt =~ '^(.*_)?(test)' ]] |