diff options
35 files changed, 1249 insertions, 839 deletions
diff --git a/ChangeLog b/ChangeLog index 36fae8a51..a2b9eadae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,132 @@ +2024-09-02 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp> + + * 53134: configure.ac: use -undefined dynamic_lookup on recent macOS + +2024-09-21 Bart Schaefer <schaefer@toltec-ubuntu> + + * 53103: Test/A08time.ztst: fix spurious test failure on Solaris + +2024-09-18 Oliver Kiddle <opk@zsh.org> + + * Philip Sequeira: 53095: Completion/Unix/Command/_chmod, + Completion/Unix/Command/_chown: fix completion for chmod/chown + --reference with escaped filename + + * 53094: configure.ac, Src/signals.h: remove unused autoconf tests + + * 53093: Src/input.c: silence compiler warning when USE_LSEEK + is not defined + + * 53092: Src/init.c: silence deprecated header warning on Linux + +2024-09-14 Bart Schaefer <schaefer@zsh.org> + + * 53088: Src/exec.c, Src/jobs.c, Test/A01grammar.ztst, + Test/A08time.ztst: enable `time' on builtins, assignments, and + other current-shell actions, including failed commands. Tests. + +2024-09-14 Oliver Kiddle <opk@zsh.org> + + * c.f. Emil Velikov: 53072: Completion/Linux/Command/_dkms: + remove completion that has been imported by the upstream project + + * 53087: Test/X05zleincarg.ztst: don't produce spurious error + when zpty is missing + + * 53086: configure.ac: change flags used for building dynamic + modules on Haiku OS + + * 53085: configure.ac, Src/init.c: support for BSDs in + $ZSH_EXEPATH implementation + + * 53084: configure.ac: yet another approach to the /dev/fd + autoconf test because of shells emulating /dev/fd + + * 53083: configure.ac, Src/Builtins/rlimits.c: handle Haiku + specific resource limit for open vnode monitors + + * 53082: configure.ac: remove a couple of unused #defines + + * 53081: INSTALL, configure.ac, Src/init.c, Src/options.c, + Src/signals.c, Src/zsh_system.h: remove old BeOS support code + + * 53080: configure.ac, Src/init.c, Src/signals.c, Src/signals.h: + remove code for systems that only have the old pre-POSIX signal() + +2024-08-31 Oliver Kiddle <opk@zsh.org> + + * Clinton Bunch: 53060: Doc/Zsh/mod_random.yo, + Src/Modules/random.c: silence build warnings + + * Clinton Bunch: 53056: Completion/Zsh/Type/_module_math_func, + Doc/Makefile.in, Doc/Zsh/mod_random.yo, Src/Modules/random.c, + Src/Modules/random.mdd, Src/Modules/random_real.c, configure.ac: + new zsh/random module defining an SRANDOM parameter and + zrand_float() and zrand_int() math functions + + * github #120: Semnodime: Completion/Unix/Command/_git: update + _git to reflect `--recursive` being an alias + + * 53058: Completion/Unix/Command/_zstd: new completion for zstd + + * 53057: Completion/Zsh/Context/_equal: complete glob qualifiers + following an equals expansion + + * 53052: Completion/X/Command/_setxkbmap: update completion with + newer options + +2024-08-26 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp> + + * unposted: Doc/Zsh/compsys.yo: remove reference to removed code + +2024-08-15 Bart Schaefer <schaefer@zsh.org> + + * unposted (see 53034): Src/lex.c, Test/A06assign.ztst: fix parsing + of Bang token in value side of array element assignment + +2024-08-13 Eric Cook <llua@gmx.com> + + * 53031: Christian Heusel: Completion/Unix/Command/_git: add + missing terminator in case statement + +2024-08-06 Bart Schaefer <schaefer@zsh.org> + + * Jun.T: 53026: Src/params.c: fix failure to free old value when + setting new value of reference + +2024-08-05 Bart Schaefer <schaefer@zsh.org> + + * 53025: Src/loop.c, Src/params.c: fix two memory leaks and two + pointer errors when encountering a named reference self-reference + + * 53023: Src/params.c: fix memory leak of unset private parameter + +2024-08-04 Bart Schaefer <schaefer@zsh.org> + + * Philippe Altherr: 53005: Src/exec.c: off-by-one error when + resetting signals on subshell entrance + +2024-08-03 Eric Cook <llua@gmx.com> + + * 52989: Completion/Unix/Command/_rsync, + Completion/Unix/Type/_remote_files: support rsync 3.2.4+ remote + filename handling. + +2024-07-28 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * 52999: Franklin Yu (adapted): Src/init.c: Import OLDPWD from + the environment if set. + +2024-07-04 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp> + + * 52985: Src/exec.c: avoid adding original param to restorelist + +2024-06-28 Bart Schaefer <schaefer@zsh.org> + + * Philippe Altherr: 52977: Src/exec.c, Test/C03traps.ztst: fix + and test regression so that ERR_EXIT and ERR_RETURN are respected + by the final command in an && / || sequence. + 2024-06-24 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp> * 52968: Doc/Makefile.in: use pdfroff to create intro.pdf diff --git a/Completion/Linux/Command/_dkms b/Completion/Linux/Command/_dkms deleted file mode 100644 index 2a3c016c5..000000000 --- a/Completion/Linux/Command/_dkms +++ /dev/null @@ -1,165 +0,0 @@ -#compdef dkms - -local curcontext="$curcontext" ign cmds opts ret=1 -local -a state line expl args subcmds dirs -local -A opt_args - -subcmds=( - 'add:add a module/version combination to the tree for builds and installs' - 'remove:remove a module from the tree' - 'build:compile a module for a kernel' - 'unbuild:undoes the build of a module' - "install:install a build module for it's corresponding kernel" - 'uninstall:uninstall a module for a kernel' - 'match:install every module that is installed for a template kernel for another kernel' - 'mkdriverdisk:create a floppy driver disk image for use when updated drivers are needed to install an OS' - 'mktarball:tar up files in the DKMS tree for a specific module' - 'ldtarball:extract a tarball created with mktarball into the DKMS tree' - 'mkrpm:create an RPM package for a module' - 'mkdeb:create a debian binary package for a module' - 'mkdsc:create a debian source package for a module' - 'mkbmdeb:create a debian package containing just binary modules' - 'mkkmp:create a Kernel Module Package source RPM for a module' - 'status:display the current status of modules, versions and kernels within the tree' - 'autoinstall:try to install the latest revision of all modules that have been installed for other kernel revisions' -) - -args=( - '(1)-m[specify module]:module:->modules' - '(1)-v[specify module version]:version' - '(-q --quiet)'{-q,--quiet}'[suppress output]' - '(--all)*'{-a,--arch}'[specify system architecture]:architecture:->architectures' - '*--directive=:directive' - '--dkmstree=:path:_directories' - '--installtree=:path:_directories' - '--sourcetree=:path:_directories' - '--dkmsframework=:path:_directories' - '--force-version-override' - '1: : _describe -t commands command subcmds' -) - -cmd=${${${subcmds%%:*}:*words}[1]} -if [[ -n $cmd ]]; then - curcontext="${curcontext%:*}-$cmd:" -else - # exclude sub-commands based on any options specified so far - for cmds opts in \ - '(remove|build|install|uninstall|match|status|mk(^kmp))' 'k' \ - '(add|remove)' '-rpm_safe_upgrade' \ - 'mk(driverdisk|kmp)' '-spec' \ - 'mk(deb|dsc|bmdeb|rpm)' '-legacy-postinst' \ - 'mk(tarball|rpm|deb|dsc)' '-(source|binary)-only' \ - '(match|build|mkkmp)' '(k|-no-(prepare|clean)-kernel|-kernelsourcedir)' \ - '(|un)install' '-no-(depmod|initrd)' \ - 'mkdriverdisk' '([dr]|-distro|-release|-size|-media)' \ - '(add|build|install|ldtarball)' '-force' \ - 'match' '-templatekernel' \ - '*tarball' '-archive' \ - '(match|build|mkkmp)' '(j*|-no-(prepare|clean)-kernel|-kernelsourcedir)' \ - '(remove|build|install|status|mk(^kmp))' '-all' \ - 'build' '-config' - do - [[ -n ${(M)words:#-${~opts}*} ]] && - subcmds=( ${(M)subcmds:#${~cmds}:*} ) - done - args+=( '(1 -)'{-V,--version}'[display version information]' ) - ign='!' # hide some uncommon options but handle their arguments -fi - -case $cmd in - remove|build|install|uninstall|mk*|status) - args+=( ': :->modules' ) - ;| - |remove|(un|)build|install|uninstall|match|status|mk(^kmp)) - args+=( '(--all)*-k[specify kernel version]:kernel:->kernels' ) - ;| - |add|remove) args+=( "${ign}--rpm_safe_upgrade" ) ;| - |mk(driverdisk|kmp)) - args+=( "${ign}--spec=:spec file:_files -g '*.spec(-.)'" ) - ;| - |(mk|ld)tarball) - args+=( "${ign}--archive=:tarball:_files -g '*.tar(-.)'" ) - ;| - |mk(deb|dsc|bmdeb|rpm)) - args+=( "${ign}--legacy-postinst=:value [1]:(0 1)" ) - ;| - |mk(tarball|rpm|deb|dsc)) args+=( "${ign}(--source-only --binaries-only)--"{source,binaries}-only ) ;| - |match|build|mkkmp) - args+=( #TODO: check ignore needed in absence of parameters - "${ign}--no-prepare-kernel" - "${ign}--no-clean-kernel" - '--kernelsourcedir=:directory:_directories' - "${ign}-j+[specify maximum number of jobs to use when building]:jobs" - ) - ;| - |(|un)install) - args+=( - "${ign}--no-depmod" - "${ign}--no-initrd" - ) - ;| - |add) - args+=( - '-c[specify location of dkms.conf file]:location:_files' - ) - ;| - |remove|(un|)build|install|status|mk(^kmp)) - args+=( '(-a --arch -k)--all[specify all relevant kernels/arches]' ) - ;| - |build) - args+=( "${ign}--config=:kernel config file:_files" ) - ;| - |add|build|install|ldtarball) - args+=( '--force[force overwriting of extant files]' ) - ;| - |match) - args+=( "${ign}--templatekernel=:kernel:->kernels" ) - ;| - |mkdriverdisk) - args+=( - "${ign}(-d --distro)"{-d,--distro=}':distribution:(redhat'{,1,2,3}' suse unitedlinux)' - "${ign}(-r --release)"{-r,--release=}':release' - "${ign}--size=:size (kb) [1440]" - "${ign}--media=:media type [floppy]:(floppy iso tar)" - ) - ;| - add) - args+=( - '3:path:_directories' - '4:tarball:_files -g "*.tar(-.)"' - ) - ;; - install) - args+=( - '3:rpm file:_files -g "*.rpm(-.)"' - ) - ;; -esac - -_arguments -C $args && ret=0 - -case $state in - modules) - dirs=( ${(e)opt_args[--dkmstree]:-/var/lib/dkms}/*/*(/) ) - dirs=( ${${(M)dirs%/*/*}#/} ) - _description modules expl module - _multi_parts -i "$expl[@]" / dirs && ret=0 - ;; - kernels) - if compset -P 1 '*/'; then - _description architectures expl architecture - compadd "$expl[@]" /lib/modules/$IPREFIX/build/arch/*(/:t) && ret=0 - else - compset -S '/*' - dirs=( /lib/modules/*(/:t) ) - _description -V kernels expl kernel - compadd "$expl[@]" -r "/ \t\n\-" ${(on)dirs} && ret=0 - fi - ;; - architectures) - _description architectures expl architecture - compadd "$expl[@]" /lib/modules/$(uname -r)/build/arch/*(/:t) && ret=0 - ;; -esac - -return ret diff --git a/Completion/Unix/Command/_chmod b/Completion/Unix/Command/_chmod index 42e3fa63b..693f348dc 100644 --- a/Completion/Unix/Command/_chmod +++ b/Completion/Unix/Command/_chmod @@ -67,13 +67,13 @@ case "$variant" in ;; esac -_arguments -C -s -S $aopts "$args[@]" && ret=0 +_arguments -C -s -S -0 $aopts "$args[@]" && ret=0 case "$state" in files) if [[ -n $opt_args[--reference] ]]; then zmodload -F zsh/stat b:zstat 2>/dev/null - typeset -i8 ref=$(zstat +mode $opt_args[--reference]) + typeset -i8 ref=$(zstat +mode $opt_args[--reference]:Q) _wanted files expl file _files -g "*(-.^f${ref#??})" && ret=0 elif [[ $line[1] = [0-7]## ]]; then _wanted files expl file _files -g "*(-.^f$line[1])" && ret=0 diff --git a/Completion/Unix/Command/_chown b/Completion/Unix/Command/_chown index 4362d6e75..bcc6aec2f 100644 --- a/Completion/Unix/Command/_chown +++ b/Completion/Unix/Command/_chown @@ -71,7 +71,7 @@ case "$variant" in esac (( $+words[(r)--reference*] )) || args+=( '(--reference)1: :->owner' ) -_arguments -C -s -S $aopts "$args[@]" '*: :->files' && ret=0 +_arguments -C -s -S -0 $aopts "$args[@]" '*: :->files' && ret=0 case $state in owner) @@ -95,8 +95,8 @@ case $state in (( $+opt_args[-h] || $+opt_args[--no-dereference] )) || deref="-" if (( $+opt_args[--reference] )); then zmodload -F zsh/stat b:zstat 2>/dev/null - usr=$(zstat +uid $opt_args[--reference]) - grp=$(zstat +gid $opt_args[--reference]) + usr=$(zstat +uid $opt_args[--reference]:Q) + grp=$(zstat +gid $opt_args[--reference]:Q) _wanted files expl file _files -g "*($deref^u$usr,$deref^g$grp)" && ret=0 return ret fi diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 22b945e38..86b8a7455 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -278,6 +278,7 @@ _git-bisect () { _arguments -C -s \ $log_options \ $revision_options && ret=0 + ;; (*) _nothing ;; @@ -664,7 +665,6 @@ _git-clone () { '(--single-branch)--no-single-branch[clone history leading up to each branch]' \ "--no-tags[don't clone any tags and make later fetches not follow them]" \ '--shallow-submodules[any cloned submodules will be shallow]' \ - '--recursive[initialize all contained submodules]' \ '(--recursive --recurse-submodules)'{--recursive,--recurse-submodules}'=-[initialize submodules in the clone]::file:__git_files' \ '--separate-git-dir[place .git dir outside worktree]:path to .git dir:_path_files -/' \ \*--server-option='[send specified string to the server when using protocol version 2]:option' \ diff --git a/Completion/Unix/Command/_rsync b/Completion/Unix/Command/_rsync index c65266dbd..81d25a3f4 100644 --- a/Completion/Unix/Command/_rsync +++ b/Completion/Unix/Command/_rsync @@ -60,7 +60,14 @@ elif compset -P 1 '*::' || compset -P 1 'rsync://*/'; then elif compset -P 'rsync://'; then _rsync_user_or_host / "$@" elif compset -P 1 '*:'; then - _remote_files -- ssh + if [[ -v opt_args[(i)client---old-args] || $RSYNC_OLD_ARGS = 1 ]]; then + _remote_files -- ssh + else + # the 3.2.4+ way that rsync handles filenames does not protect *, ? and [] + # so those characters still need to be escaped to prevent being treated as + # a pattern in the remote shell. + _remote_files -Q '[][*?]' -- ssh + fi else _rsync_user_or_host : "$@" fi @@ -236,6 +243,7 @@ _rsync() { '*--include=[do not exclude files matching pattern]:pattern' \ '--files-from=[read list of source-file names from specified file]:file:_files' \ '(-0 --from0)'{-0,--from0}'[all *-from file lists are delimited by nulls]' \ + '--old-args[disable the modern arg-protection idiom]' \ '(-s --secluded-args)'{-s,--secluded-args}'[use the protocol to safely send arguments]' \ "--trust-sender[trust the remote sender's file list]" \ '--copy-as=[specify user & optional group for the copy]:user:_rsync_users_groups' \ diff --git a/Completion/Unix/Command/_zstd b/Completion/Unix/Command/_zstd new file mode 100644 index 000000000..92c4a8e41 --- /dev/null +++ b/Completion/Unix/Command/_zstd @@ -0,0 +1,118 @@ +#compdef zstd zstdmt unzstd zstdcat -redirect-,<,unzstd=unzstd -redirect-,>,zstd=unzstd -redirect-,<,zstd=zstd + +local ign +local -a levels implied noopt args blksize + +(( $#words > 2 )) && ign='!' + +[[ $compstate[context] = redirect ]] && noopt=( -- ) +case "$service" in + zstdmt) implied=( -T0 ) ;; + unzstd) (( $words[(I)(-z|--compress)] )) || implied=( -d ) ;; + zstdcat) + implied=( -dcf ) + (( $words[(I)(-z|--compress)] )) && implied=( -cf ) + ;; +esac +words[1]+=( $implied $noopt ) +(( CURRENT += $#implied + $#noopt )) + +if (( $words[(r)--ultra] )); then + levels=( -{20..22} ) +else + levels=( -{1..19} ) +fi + +blksize=( + '(M -B --block-size)'{-B+,--block-size=-}'[cut file into independent blocks of specified size]: :_numbers -d "no block" -u bytes size KiB MiB' +) +if (( $words[(r)--train] )); then + args=( $blksize + '(M)--train-cover=-[use the cover algorithm with optional arguments]::parameter' + '(M)--train-fastcover=-[use the fast cover algorithm with optional arguments]::parameter' + '(M)--train-legacy=-[use the legacy algorithm with selectivity]::selectivity [9]' + '-o[specify dictionary name]:dictionary name [dictionary]' + '(M)--maxdict=[limit dictionary to specified size]: :_numbers -u bytes -d 112640 size KiB MiB' + '(M)--dictID=[force dictionary ID to specified value]:value [random]' + '*:files:_files' + ) +elif (( $words[(I)-b[0-9]#] )); then + args=( $blksize + '(M)-e-[test all compression levels successively from -b level]: :_numbers -d 3 -l 1 -m 19 level' + '(M)-i-[specify minimum evaluation time]: :time (seconds) [3]' + '(M -B --block-size)'{-B+,--block-size=-}'[cut file into independent blocks of specified size]: :_numbers -d "no block" -u bytes size KiB MiB' \ + '(M)-S[output one benchmark result per input file]' + '(M)--priority=-[set process priority]:priority:(rt)' + '*:files:_files -g "^*.(|t)zst(-.)"' + ) +elif (( $words[(I)(-d|--decompress|--uncompress|-l|--list|-t|--test)] )); then + args=( + '(M --sparse -c --stdout)--no-sparse[sparse mode]' + '(M --no-sparse -o)--sparse[sparse mode]' + '(--sparse)-o[specify output file]:file:_files -g "^*.(|t)zst(-.)"' + "(M)--no-check[ignore checksums in compressed frame]" + '!(M --no-check)'{-C,--check} + '*:files:_files -g "*.(|t)zst(-.)"' + ) +else + args=( + "(M)--no-check[don't add/verify XXH64 integrity checksums]" + '!(M --no-check)'{-C,--check} + "(M)--no-content-size[don't include original file size in header]" + '!(M --no-content-size)--content-size' + "(M)--no-progress[don't show the progress bar but keep other messages]" + '!(M --no-progress)--progress' + "(M --adapt --fast --ultra ${levels[*]})"$^levels + '(M --fast)--ultra[enable levels beyond 19, up to 22]' + '--long=-[enable long distance matching with given window log]:window log [27]' + "(M --adapt --ultra ${levels[*]})--fast=-[switch to very fast compression levels]:level [1]" + "(M --fast ${levels[*]})--adapt=-[dynamically adapt compression level to I/O conditions]: :_values -s , 'range' + 'min\:level' '(min)max\:level'" + '(M)'--{no-,}row-match-finder'[force usage of fast row-based matchfinder for greedy, lazy, and lazy2 strategies]' + "(-D)--patch-from=[specify the file to be used as a reference point for zstd's diff engine]: :_files" + '(--single-thread -T --threads)'{-T-,--threads=}'[spawn specified number of threads]:threads [1]' + '(M -B --block-size)'{-B-,--block-size=-}'[select block size of each job]: :_numbers -u bytes -d 0\:automatic "block size" KiB MiB' + '(M -T --threads --rsyncable)--single-thread[use a single thread for both I/O and compression (result different than -T1)]' + '(M)--auto-threads=[use either physical cores or logical cores as default when specifying -T0]:cores [physical]:(physical logcial)' + '(M --single-thread)--rsyncable[compress using a rsync-friendly method]' + '(M)--exclude-compressed[only compress files that are not already compressed]' + '(M --size-hint)--stream-size=-[specify exact size of streaming input from stdin]: :_numbers -u bytes size KiB MiB' + '(M --stream-size)--size-hint=[indicate size of streamed input to optimize compression parameters]: :_numbers -u bytes size KiB MiB' + '(M)--target-compressed-block-size=[generate compressed block of approximately targeted size]: :_numbers -u bytes limit KiB MiB' + "(M)--no-dictID[don't write dictID into header (dictionary compression only)]" + '(M --no-compress-literals --compress-literals)'--{no-,}compress-literals'[force (un)compressed literals]' + '(M)--show-default-cparams[show compression parameters for each file]' + '(--test)-o[specify output file]:file:_files -g "*.(|t)zst(-.)"' + '--format=-[compress files to specified format]:format [zstd]:(zstd gzip xz lzma lz4)' + '--zstd=[specify advanced compression options]: :_values -s , "option" + strategy\:strategy "windowLog\:bits (10-31)" "hashLog\:bits (6-30)" + "chainLog\:bits (6-31)" "searchLog\:searches" "minMatch\:length" + "targetLength\:length" "overlapLog\:size" "ldmHashLog\:size" + "ldmMinMatch\:length" "ldmBucketSizeLog\:size" "ldmHashRateLog\:frequency"' + '*:files:_files -g "^*.(|t)zst(-.)"' + ) +fi + +_arguments -s -S : $args \ + "$ign(- *)"{-h,--help}'[display help message]' \ + "$ign(- *)"{-V,--version}'[display version number]' \ + '(--patch-from)-D[use specified dictionary for compression or decompression]:dictionary' \ + '(-f --force)'{-f,--force}'[force overwrite]' \ + '--rm[remove source file(s) after successful compression or decompression]' \ + '!(-k --keep --rm)'{-k,--keep} \ + '(-c --stdout --no-sparse --test)'{-c,--stdout}'[write on standard output]' \ + '(-M --memory)'{-M-,--memory=}'[set a memory usage limit]: :_numbers -u bytes limit KiB MiB' \ + \*{-v,--verbose}'[display more information]' \ + \*{-q,--quiet}'[suppress messages]' \ + '-r[operate recursively on directories]' \ + '--filelist=[read list of files to operate upon from file]: :_files' \ + '--output-dir-flat=[store processed files in directory]: :_directories' \ + '--output-dir-mirror=[store processed files in directory respecting original structure]: :_directories' \ + '--trace=[log tracing information to file]: :_files' \ + + '(M)' \ + \!{-z,--compress,--uncompress} \ + '(-B --block-size)'{-d,--decompress}'[decompress]' \ + '(-B --block-size)'{-l,--list}'[print information about zstd compressed files]' \ + '(-c --stdout -o --rm -B --block-size)'{-t,--test}'[test compressed file integrity]' \ + '(-c --stdout -D -k --keep --rm)--train=[create a dictionary from a training set of files]' \ + '(-c --stdout -k --keep --rm)-b-[benchmark file(s), using specified compression level]:: :_numbers -d 3 -l 1 -m 19 level' diff --git a/Completion/Unix/Type/_remote_files b/Completion/Unix/Type/_remote_files index 93e1b7f43..15c20e5c1 100644 --- a/Completion/Unix/Type/_remote_files +++ b/Completion/Unix/Type/_remote_files @@ -11,6 +11,8 @@ # - -g: specify a pattern to match against files # p, = and * glob qualifiers supported # - -h: specify the remote host, default is ${IPREFIX%:} +# - -Q: specify a pattern of characters to escape in the returned filenames, +# instead of shell metacharacters that ${(q)name} does # - -W: specify the parent directory to list files from, # default is the home directory # @@ -31,14 +33,14 @@ # There should be coloring based on all the different ls -F classifiers. -local expl rempat remfiles remdispf remdispd args cmd suf ret=1 +local expl rempat remfiles remdispf{,q} remdispd{,q} args cmd suf ret=1 local -a args cmd_args -local glob host dir dirprefix +local glob host dir esc dirprefix if zstyle -T ":completion:${curcontext}:files" remote-access; then # Parse options to _remote_files. Stops at the first "--". - zparseopts -D -E -a args / g:=glob h:=host W:=dir + zparseopts -D -E -a args / g:=glob h:=host W:=dir Q:=esc (( $#host)) && shift host || host="${IPREFIX%:}" args=( ${argv[1,(i)--]} ) @@ -85,6 +87,14 @@ if zstyle -T ":completion:${curcontext}:files" remote-access; then remdispf=( ${(M)remdispf:#${~glob[2]}} ) fi + if (( $#esc )); then + remdispfq=(${${remdispf%[*=|]}//(#b)(${~esc[2]})/\\$match[1]}) + remdispdq=(${${remdispd%/}//(#b)(${~esc[2]})/\\$match[1]}) + else + remdispfq=(${(q)remdispf%[*=|]}) + remdispdq=(${(q)remdispd%/}) + fi + local -a autoremove [[ -o autoremoveslash ]] && autoremove=(-r "/ \t\n\-") @@ -92,9 +102,9 @@ if zstyle -T ":completion:${curcontext}:files" remote-access; then while _tags; do while _next_label remote-files expl ${suf:-remote directory}; do [[ -n $suf ]] && - compadd "$args[@]" "$expl[@]" -d remdispf -- ${(q)remdispf%[*=|]} && ret=0 + compadd "$args[@]" "$expl[@]" -d remdispf -- $remdispfq && ret=0 compadd ${suf:+-S/} $autoremove "$args[@]" "$expl[@]" -d remdispd \ - -- ${(q)remdispd%/} && ret=0 + -- $remdispdq && ret=0 done (( ret )) || return 0 done diff --git a/Completion/X/Command/_setxkbmap b/Completion/X/Command/_setxkbmap index 882a6f939..0850d5419 100644 --- a/Completion/X/Command/_setxkbmap +++ b/Completion/X/Command/_setxkbmap @@ -1,101 +1,119 @@ #compdef setxkbmap -# TODO: -# model, option, symbols and types suggestions -# take -layout and -variant into account - -_setxkbmap() { - emulate -L zsh - setopt extendedglob - - # xkb files may be in different places depending on system - local dir sourcedir fullname - local -a searchdirs=(${XDG_DATA_HOME:-~/.local/share} ${(s.:.)XDG_DATA_DIRS:-/usr/lib:/usr/share:/usr/local/lib:/usr/local/share}) - for dir in $searchdirs; do - fullname="$dir/X11/xkb" - if [ -d $fullname ] ; then - sourcedir=$fullname - break - fi - done - [ -d $sourcedir ] || return 1 - - local -a arguments - - arguments=( - '-compat[compatibility map]:compatibility:_setxkbmap_compat' - '-config[configuration file]:configuration:_files' - '-display[display]:display:_x_display' - '-geometry[geometry component]:geometry:_setxkbmap_geometry' - '-model[model name]:model:' - '-option[xkb option]:option:' - '(-)'-print'[print component names]' - '-rules[rules file]:rules:_files' - '-symbols[symbols components]:symbols:' - '(-)'{-help,-h}'[display help message]' - '-synch[force synchronization]' - '-types[types components]:types:' - '(-verbose -v)'{-verbose,-v}'[set verbosity level]:verbosity:(0 1 2 3 4 5 6 7 8 9)' - '*::keyboard:_setxkbmap_dispatcher' +local curcontext="$curcontext" sourcedir layout ret=1 +local -a state state_descr line expl matches suf +local -A opt_args + +_arguments -C \ + '(-)'{-\?,-help}'[display help message]' \ + '-compat[compatibility map]:compatibility:->compatmaps' \ + '-config[configuration file]:configuration:_files' \ + '-device[specify numeric id of the input device]:device:->devices' \ + '-display[display]:display:_x_display' \ + '-geometry[geometry component]:geometry:->geometries' \ + '*-I+[add a directory to be searched for layout or rules files]: :_directories' \ + '-keycodes[specify keycodes component name]:name' \ + '-keymap[specify keymap to load]:keymap' \ + '-layout[specify layout used to choose component names]:layout:->layouts' \ + '-model[specify model used to choose component names]:model:->models' \ + '*-option[add an xkb option]:option:->options' \ + '(-)'-print'[print a complete xkb_keymap description]' \ + '-query[print the current layout settings]' \ + '-rules[specify rules file to use]:rules:->rules' \ + '-symbols[specify symbols component name]:symbol' \ + '-synch[force synchronization]' \ + '-types[types components]:type:->types' \ + '(-verbose -v)'{-verbose,-v}'[set verbosity level]:verbosity:(0 1 2 3 4 5 6 7 8 9)' \ + '(-)-version[display version information]' \ + '-variant[specify layout variant used to choose component name]:variant:->variants' \ + '1:layout:->layouts' \ + '2:variant:->variants' \ + '*:option:->options' && ret=0 + +if [[ -n $state ]]; then + local open='(' close=')' + compquote open close + + layout=${opt_args[-layout]:-$line[1]} + if [[ $state = layouts ]]; then + compset -P '*,' + if compset -P 1 '*\('; then + layout="${${IPREFIX%$open}##*,}" + state=variants state_descr=variant + suf=( -S"$close$compstate[quote] " ) + else + suf=( -S$open -r ",('\" \t\n\-" ) + fi + fi + + _description $state expl $state_descr + if (( $+commands[localectl] )); then + case $state in + layouts) matches=( $(_call_program layouts localectl list-x11-keymap-layouts) ) ;; + models) matches=( $(_call_program layouts localectl list-x11-keymap-models) ) ;; + options) matches=( $(_call_program layouts localectl list-x11-keymap-options) ) ;; + variants) matches=( $(_call_program layouts localectl list-x11-keymap-variants $layout) ) ;; + esac + fi + if (( ! $#matches )); then + sourcedir=$(pkg-config xkeyboard-config --variable=xkb_base 2>/dev/null) + [[ -z $sourcedir ]] && sourcedir=( + ${XDG_DATA_HOME:-~/.local/share}/X11/xkb(N/) + ${(s.:.)XDG_DATA_DIRS:-/usr/lib:/usr/share:/usr/local/lib:/usr/local/share}/X11/xkb(N/) ) - _arguments $arguments -} - -_setxkbmap_dispatcher () { - - case $CURRENT in - 1) - _setxkbmap_layout - ;; - 2) - _setxkbmap_variant "$words[1]" - ;; + (( $#sourcedir )) && case $state in + layouts) matches=( $sourcedir/symbols/**/^README(.Ne."REPLY=\${REPLY#*/symbols/}".) ) ;; + compatmaps) matches=( $sourcedir/compat/^README(.:t) ) ;; + models) matches=( $(sed -n '/modelList/,/\/modelList/ s, *<name>\(.*\)</name>,\1,p' $sourcedir/rules/(evdev|base).xml(.N[1])) ) ;; + options) matches=( $(sed -n '/optionList/,/\/optionList/ s, *<name>\(.*\)</name>,\1,p' $sourcedir/rules/(evdev|base).xml(.N[1])) ) ;; + rules) matches=( $sourcedir/rules/*.lst(-.:t:r) ) ;; + types) matches=( $sourcedir/types/^README(.:t) ) ;; + variants) + [[ -n $layout && -r $sourcedir/symbols/$layout ]] && matches=( + ${${${(M)${(f)"$(<$sourcedir/symbols/$layout)"}:#*xkb_symbols*\"([^\"])##\"*}##*xkb_symbols([^\"])##\"}%%\"*} + ) + ;; + geometries) + if compset -P 1 '*\('; then + layout="${${IPREFIX%$open}##*,}" + suf=( -S"$close$compstate[quote] " ) + matches=( $(sed -n -e '/xkb_geometry/ s/[^"]*"\([^"]*\).*/\1/p' $sourcedir/geometry/${IPREFIX%%[\\(]#}(.N)) ) + else + suf=( -S$open -r "('\" \t\n\-" ) + matches=( $sourcedir/geometry/^README(.:t) ) + fi + ;; + devices) + # copied from _xinput + if (( $+commands[xinput] )); then + local -a ids names disp + local out + ids=( ${${(f)"$(_call_program input-devices xinput list --id-only)"}#? } ) + names=( ${${(f)"$(_call_program input-devices xinput list --name-only)"}#? } ) + disp=( ${(f)"$(_call_program input-devices xinput list --short)"} ) + + if [[ $PREFIX$SUFFIX = [^-]*[^0-9]* ]]; then + # match based on the names but insert IDs + compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D ids -D disp -a names + compadd "$expl[@]" -U -ld disp -a ids && ret=0 + + zstyle -s ":completion:${curcontext}:input-devices" insert-ids out || out=menu + case "$out" in + menu) compstate[insert]=menu ;; + single) [[ $#ids -ne 1 && $compstate[insert] != menu ]] && + compstate[insert]= ;; + *) [[ ${#:-$PREFIX$SUFFIX} -gt ${#compstate[unambiguous]} ]] && + compstate[insert]=menu ;; + esac + else + compadd "$expl[@]" -M 'B:0=' -o nosort -ld disp -a ids && ret=0 + fi + fi + return ret + ;; esac -} - -_setxkbmap_files () { - local dir="$1" - local label="$2" - - local -a fullpath shortpath expl - - fullpath=($sourcedir/$dir/**/*~*README(.)) - shortpath=(${fullpath#$sourcedir\/$dir\/}) - - _wanted layout expl $label compadd -a - shortpath - -} - -(( $+functions[_setxkbmap_compat] )) || -_setxkbmap_compat() { - _setxkbmap_files "compat" "compatibility" -} - -(( $+functions[_setxkbmap_layout] )) || -_setxkbmap_layout () { - _setxkbmap_files "symbols" "layout" -} - -(( $+functions[_setxkbmap_geometry] )) || -_setxkbmap_geometry () { - _setxkbmap_files "geometry" "geometry" -} - -(( $+functions[_setxkbmap_variant] )) || -_setxkbmap_variant () { - local file=$sourcedir/symbols/${1} - local -a variants lines expl - - if [ ! -f $file ]; then - _message "no such layout: ${1}" - return 1 - fi - - lines=("${(f)$(< ${file})}") - variants=(${${${(M)lines:#*xkb_symbols*\"([^\"])##\"*}##*xkb_symbols([^\"])##\"}%%\"*}) - - _wanted variant expl 'variant' compadd -a variants - -} + fi + compadd "$expl[@]" $suf -a matches && ret=0 +fi -_setxkbmap "$@" +return ret diff --git a/Completion/Zsh/Context/_equal b/Completion/Zsh/Context/_equal index 58a415d56..5cdeea264 100644 --- a/Completion/Zsh/Context/_equal +++ b/Completion/Zsh/Context/_equal @@ -1,3 +1,11 @@ #compdef -equal- -_path_commands +local -a match mbegin mend + +if _have_glob_qual $PREFIX; then + compset -p ${#match[1]} + compset -S '[^\)\|\~]#(|\))' + _globquals +else + _path_commands +fi diff --git a/Completion/Zsh/Type/_module_math_func b/Completion/Zsh/Type/_module_math_func index 5044bdf4c..e92b78b71 100644 --- a/Completion/Zsh/Type/_module_math_func +++ b/Completion/Zsh/Type/_module_math_func @@ -2,7 +2,7 @@ local mod local -a funcs alts -local -a modules=( example mathfunc system ) +local -a modules=( example mathfunc system random ) for mod in $modules; do funcs=( ${${${(f)"$(zmodload -Fl zsh/$mod 2>/dev/null)"}:#^+f:*}##+f:} ) diff --git a/Doc/Makefile.in b/Doc/Makefile.in index 401fb942b..fa2a336ad 100644 --- a/Doc/Makefile.in +++ b/Doc/Makefile.in @@ -68,7 +68,7 @@ Zsh/mod_hlgroup.yo Zsh/mod_langinfo.yo \ Zsh/mod_ksh93.yo Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo \ Zsh/mod_nearcolor.yo Zsh/mod_newuser.yo \ Zsh/mod_parameter.yo Zsh/mod_pcre.yo Zsh/mod_private.yo \ -Zsh/mod_regex.yo Zsh/mod_sched.yo Zsh/mod_socket.yo \ +Zsh/mod_regex.yo Zsh/mod_random.yo Zsh/mod_sched.yo Zsh/mod_socket.yo \ Zsh/mod_stat.yo Zsh/mod_system.yo Zsh/mod_tcp.yo \ Zsh/mod_termcap.yo Zsh/mod_terminfo.yo \ Zsh/mod_watch.yo \ diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index f75298a1b..77627bacc 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -5448,10 +5448,6 @@ example(local expl _wanted tag expl 'description' \ compadd -- var(match1) var(match2)...) -See also the use of tt(_wanted) in the example function in -ifzman(the subsection `Dynamic named directories' in zmanref(zshexpn))\ -ifnzman(noderef(Dynamic named directories)). - Note that, as for tt(_requested), the var(command) must be able to accept options to be passed down to tt(compadd). diff --git a/Doc/Zsh/mod_random.yo b/Doc/Zsh/mod_random.yo new file mode 100644 index 000000000..4f5622e61 --- /dev/null +++ b/Doc/Zsh/mod_random.yo @@ -0,0 +1,56 @@ +COMMENT(!MOD!zsh/random +Some High-quality randomness parameters and functions. +!MOD!) +The tt(zsh/random) module gets random data from the kernel random pool. If no +kernel random pool can be found, the module will not load. + +subsect(Parameters) + +startitem() +vindex(SRANDOM) +item(tt(SRANDOM)) ( +A random positive 32-bit integer between 0 and 4,294,967,295. This parameter +is read-only. The name was chosen for compatibility with Bash and to +distinguish it from tt(RANDOM) which has a documented repeatable behavior. +) +enditem() + +subsect(Math Functions) + +startitem() +item(tt(zrand_float+LPAR()RPAR())) ( +Returns a random floating point number between 0 and 1 inclusive. +) +enditem() + +startitem() +item(tt(zrand_int)+LPAR()tt(upper), tt(lower), tt(inclusive)RPAR()) ( +Returns a random integer between tt(lower) and tt(upper). All parameters are +optional. If none are specified it is equivalent to +tt(SRANDOM). + +tt(upper) is the upper bound on the resultant number and defaults to +4,294,967,295. + +tt(lower) is the lower bound and defaults to 0. + +The defaults of these two arguments are also the maximum and minimum to which +either can be set. + +tt(inclusive) is a flag that controls whether the result is ever equal to +tt(upper). By default it is not. If this argument is set to a non-zero value +then it may be. + +This is to facilitate a construct like tt($a[zrand_int+LPAR()$#a+RPAR()+1]) rather +than tt($a[zrand_int+LPAR()$#a-1+RPAR()+1]). +For example, if $#a is 16, you would use tt(zrand_int+LPAR()16RPAR()) which has +16 possible return values 0-15. Because the function can return zero, in order +to use it as an array index from 1-16 you need to add one. It would +be an array index range error for it to also potentially return 16 ($#a). You +could, however, use the construct tt(zrand_int+LPAR()16,1,1+RPAR()) instead of +adding 1 to achieve the same result, but it is more verbose. + +Most statistics algorithms seem to also expect 0 to tt(upper)-1, so this was +deemed the most commonly desired case and chosen as the default. +) +enditem() diff --git a/INSTALL b/INSTALL index f347a4480..8b139fa9b 100644 --- a/INSTALL +++ b/INSTALL @@ -576,13 +576,6 @@ shell is running in some privileged mode. This is turned off by default as on some systems non-standard headers (in particular AIX) are required. A direct fix for that problem would be appreciated. -A test for the function tcsetpgrp is turned on by default. The test -needs to run the function to determine if the implementation is -usable. However, this can cause problems when configure is run without -a controlling terminal (eg. from cron). To avoid this, use ---with-tcsetpgrp or --without-tcsetpgrp to tell configure whether the -function should be used. - Options For Configure --------------------- diff --git a/Src/Builtins/rlimits.c b/Src/Builtins/rlimits.c index 5f9c84b0f..f25dd2530 100644 --- a/Src/Builtins/rlimits.c +++ b/Src/Builtins/rlimits.c @@ -171,6 +171,10 @@ static const resinfo_T known_resources[] = { {RLIMIT_TCACHE, "cachedthreads", ZLIMTYPE_NUMBER, 1, 'N', "cached threads"}, # endif +# ifdef HAVE_RLIMIT_NOVMON /* Haiku */ + {RLIMIT_NOVMON, "vnodemonitors", ZLIMTYPE_NUMBER, 1, + 'N', "open vnode monitors"}, +# endif }; /* resinfo[RLIMIT_XXX] points to the corresponding entry diff --git a/Src/Modules/random.c b/Src/Modules/random.c new file mode 100644 index 000000000..88ac9543c --- /dev/null +++ b/Src/Modules/random.c @@ -0,0 +1,326 @@ +/* + * random.c - module to access kernel random sources. + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 2022 Clinton Bunch + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Clinton Bunch or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Clinton Bunch and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Clinton Bunch and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Clinton Bunch and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "random.mdh" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> + +#include <stdint.h> + +#ifdef HAVE_SYS_RANDOM_H +#include <sys/random.h> +#endif + +/* Simplify select URANDOM specific code */ +#if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_GETRANDOM) +#define USE_URANDOM +#endif + +/* buffer to pre-load integers for SRANDOM to lessen the context switches */ +static uint32_t rand_buff[8]; +static int buf_cnt = -1; + +#ifdef USE_URANDOM +/* File descriptor for /dev/urandom */ +int randfd = -1; +#endif /* USE_URANDOM */ + +static zlong get_srandom(UNUSED(Param p)); + +/**/ +ssize_t +getrandom_buffer(void *buf, size_t len) +{ + ssize_t ret; +#ifndef HAVE_ARC4RANDOM_BUF + size_t val = 0; + uint8_t *bufptr = buf; +#endif + + do { + errno = 0; +#ifdef HAVE_ARC4RANDOM_BUF + arc4random_buf(buf,len); + ret = len; +#elif defined(HAVE_GETRANDOM) + ret=getrandom(bufptr,(len - val),0); +#else + ret=read(randfd,bufptr,(len - val)); +#endif + if (ret < 0) { + if (errno != EINTR || errflag || retflag || breaks || contflag) { + zwarn("Unable to get random data: %e.", errno); + return -1; + } + } +#ifndef HAVE_ARC4RANDOM_BUF + bufptr += ret; + val += ret; +#endif + } while (ret < len); + return ret; +} + +/* + * Generate count number of random 32-bit integers between 0 and max-1 + * Got this algorithm from + *https://lemire.me/blog/2016/06/30/fast-random-shuffling/ + * adapting the public domain code. + * + */ + +/**/ +void +get_bound_random_buffer(uint32_t *buffer, size_t count, uint32_t max) +{ + uint64_t multi_result; + uint32_t threshold; + uint32_t leftover; + + size_t i; /* loop counter */ + + getrandom_buffer((void*) buffer, count*sizeof(uint32_t)); + if (max == UINT32_MAX) + return; + + for(i=0;i<count;i++) { + multi_result = ((uint64_t) buffer[i]) * (uint64_t) max; + leftover = (uint32_t) multi_result; + + /* + * The following if statement should (according to Google's Gemini) + * only be executed with a probability of 1/2**32 or 2.33e-10 + */ + if(leftover < max) { + threshold= -max % max; + while (leftover < threshold) { + uint32_t j=get_srandom(NULL); + multi_result=(uint64_t) j * (uint64_t) max; + leftover= (uint32_t) multi_result; + } + } + buffer[i]=multi_result >> 32; + } +} + +/* + * Provides for the SRANDOM parameter and returns an unsigned 32-bit random + * integer. + */ + +/**/ +static zlong +get_srandom(UNUSED(Param pm)) { + + if(buf_cnt <= 0) { + getrandom_buffer((void*) rand_buff,sizeof(rand_buff)); + buf_cnt=sizeof(rand_buff)/sizeof(rand_buff[0]); + } + return rand_buff[--buf_cnt]; +} + +/* + * Implements math function zrand_int takes 0 to 3 arguments an upper bound, + * a lower bound and a flag as to whether the range is inclusive or not. The + * default is exclusive. If neither upper or lower is specified this is no + * different than SRANDOM. + */ + +/**/ +static mnumber +math_zrand_int(UNUSED(char *name), int argc, mnumber *argv, UNUSED(int id)) +{ + mnumber ret; + uint32_t i; + zlong lower=0, upper=UINT32_MAX,incl=0, diff; + + ret.type = MN_INTEGER; + + switch (argc) { + case 0: ret.u.l=get_srandom(NULL); + return ret; + break; + case 3: incl = (argv[2].u.l != 0)?1:0; + case 2: lower = argv[1].u.l; + case 1: upper = argv[0].u.l; + default: diff = upper-lower+incl; + } + + if (lower < 0 || lower >= UINT32_MAX) { + zwarn("Lower bound (%z) out of range: 0-4294967295",lower); + } else if (upper < lower) { + zwarn("Upper bound (%z) must be greater than Lower Bound (%z)",upper,lower); + } else if (upper < 0 || upper >= UINT32_MAX) { + zwarn("Upper bound (%z) out of range: 0-4294967295",upper); + } + + if ( diff == 0 ) { + ret.u.l=upper; /* still not convinced this shouldn't be an error. */ + } else { + get_bound_random_buffer(&i,1,(uint32_t) diff); + ret.u.l=i+lower; + } + return ret; +} + +/* + * Implements the mathfunc zrand_float and returns a random floating-point + * number between 0 and 1. + * + */ + +/**/ +static mnumber +math_zrand_float(UNUSED(char *name), UNUSED(int argc), UNUSED(mnumber *argv), + UNUSED(int id)) +{ + mnumber ret; + double r; + + r = random_real(); + if (r < 0) { + zwarnnam(name, "Failed to get sufficient random data."); + } + ret.type = MN_FLOAT; + ret.u.d = r; + + return ret; +} + +static const struct gsu_integer srandom_gsu = +{ get_srandom, nullintsetfn, stdunsetfn }; + +static struct paramdef patab[] = { + {"SRANDOM", PM_INTEGER | PM_READONLY_SPECIAL | PM_HIDEVAL, NULL, + &srandom_gsu, NULL, NULL, NULL}, +}; + +static struct mathfunc mftab[] = { + NUMMATHFUNC("zrand_float", math_zrand_float, 0, 0, 0), + NUMMATHFUNC("zrand_int", math_zrand_int, 0, 3, 0), +}; + +static struct features module_features = { + NULL, 0, + NULL, 0, + mftab, sizeof(mftab)/sizeof(*mftab), + patab, sizeof(patab)/sizeof(*patab), + 0 +}; + +/**/ +int +setup_(UNUSED(Module m)) +{ +#ifdef USE_URANDOM + /* Check for the existence of /dev/urandom */ + + struct stat st; + + errno=0; + if (stat("/dev/urandom",&st) < 0) { + zwarn("Error getting kernel random pool: %e.", errno); + return 1; + } + + errno=0; + if (!(S_ISCHR(st.st_mode)) ) { + zwarn("Error getting kernel random pool: %e.", errno); + return 1; + } +#endif /* USE_URANDOM */ + return 0; +} + +/**/ +int +features_(Module m, char ***features) +{ + *features = featuresarray(m, &module_features); + return 0; +} + +/**/ +int +enables_(Module m, int **enables) +{ + return handlefeatures(m, &module_features, enables); +} + +/**/ +int +boot_(UNUSED(Module m)) +{ +#ifdef USE_URANDOM + /* + * Open /dev/urandom. Here because of a weird issue on HP-UX 11.31 + * When opening in setup_ open returned 0. In boot_, it returns + * an unused file descriptor. Decided against ifdef HPUX as it works + * here just as well for other platforms. + * + */ + + int tmpfd=-1; + + errno=0; + if ((tmpfd = open("/dev/urandom", O_RDONLY)) < 0) { + zwarn("Could not access kernel random pool: %e.",errno); + return 1; + } + randfd = movefd(tmpfd); + addmodulefd(randfd,FDT_MODULE); + if (randfd < 0) { + zwarn("Could not access kernel random pool."); + return 1; + } +#endif /* USE_URANDOM */ + return 0; +} + +/**/ +int +cleanup_(Module m) +{ + return setfeatureenables(m, &module_features, NULL); +} + +/**/ +int +finish_(UNUSED(Module m)) +{ +#ifdef USE_URANDOM + if (randfd >= 0) + zclose(randfd); +#endif /* USE_URANDOM */ + return 0; +} diff --git a/Src/Modules/random.mdd b/Src/Modules/random.mdd new file mode 100644 index 000000000..7a75f29ff --- /dev/null +++ b/Src/Modules/random.mdd @@ -0,0 +1,7 @@ +name=zsh/random +link=either +load=yes + +autofeatures="p:SRANDOM f:zrand_float f:zrand_int" + +objects="random.o random_real.o" diff --git a/Src/Modules/random_real.c b/Src/Modules/random_real.c new file mode 100644 index 000000000..4a8fcae19 --- /dev/null +++ b/Src/Modules/random_real.c @@ -0,0 +1,213 @@ +/* This file contains code under different copyrights separated by */ +/* ====@@@@@=== */ + +/* + * random_real.c - module to access kernel random sources. + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 2022 Clinton Bunch + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Clinton Bunch or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Clinton Bunch and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Clinton Bunch and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Clinton Bunch and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "random.mdh" + +#include <math.h> +#include <stdint.h> +#include <errno.h> + + +/* Count the number of leading zeros, hopefully in gcc/clang by HW + * instruction */ +#if defined(__GNUC__) || defined(__clang__) +#define clz64(x) __builtin_clzll(x) +#else +#define clz64(x) _zclz64(x) + +/**/ +int +_zclz64(uint64_t x) { + int n = 0; + + if (x == 0) + return 64; + + if (!(x & 0xFFFFFFFF00000000ull)) { + n+=32; + x<<=32; + } + if (!(x & 0xFFFF000000000000ull)) { + n+=16; + x<<=16; + } + if (!(x & 0xFF00000000000000ull)) { + n+=8; + x<<=8; + } + if (!(x & 0xF000000000000000ull)) { + n+=4; + x<<=4; + } + if (!(x & 0xC000000000000000ull)) { + n+=2; + x<<=1; + } + if (!(x & 0x8000000000000000ull)) { + n+=1; + } + return n; +} +#endif /* __GNU_C__ or __clang__ */ + +/**/ +uint64_t +random_64bit(void) { + uint64_t r; + + if(getrandom_buffer(&r,sizeof(r)) < 0) { + zwarn("zsh/random: Can't get sufficient random data."); + return 1; /* 0 will cause loop */ + } + + return r; +} + +/* ====@@@@@=== */ +/* Following code is under the below copyright, despite changes for error + * handling and removing GCCisms */ + +/*- + * Copyright (c) 2014 Taylor R. Campbell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Uniform random floats: How to generate a double-precision + * floating-point numbers in [0, 1] uniformly at random given a uniform + * random source of bits. + * + * See<http://mumble.net/~campbell/2014/04/28/uniform-random-float> + * for explanation. + * + * Updated 2015-02-22 to replace ldexp(x, <constant>) by x * ldexp(1, + * <constant>), since glibc and NetBSD libm both have slow software + * bit-twiddling implementations of ldexp, but GCC can constant-fold + * the latter. + */ + +/* + * random_real: Generate a stream of bits uniformly at random and + * interpret it as the fractional part of the binary expansion of a + * number in [0, 1], 0.00001010011111010100...; then round it. + */ + +/**/ +double +random_real(void) +{ + int exponent = 0; + uint64_t significand = 0; + uint64_t r = 0; + unsigned shift; + + /* + * Read zeros into the exponent until we hit a one; the rest + * will go into the significand. + */ + while (significand == 0) { + exponent -= 64; + + /* Get random_64bit and check for error */ + errno = 0; + significand = random_64bit(); + if (errno) + return -1; + /* + * If the exponent falls below -1074 = emin + 1 - p, + * the exponent of the smallest subnormal, we are + * guaranteed the result will be rounded to zero. This + * case is so unlikely it will happen in realistic + * terms only if random_64bit is broken. + */ + if (exponent < -1074) + return 0; + } + + /* + * There is a 1 somewhere in significand, not necessarily in + * the most significant position. If there are leading zeros, + * shift them into the exponent and refill the less-significant + * bits of the significand. Can't predict one way or another + * whether there are leading zeros: there's a fifty-fifty + * chance, if random_64bit is uniformly distributed. + */ + shift = clz64(significand); + if (shift != 0) { + + errno = 0; + r = random_64bit(); + if (errno) + return -1; + + exponent -= shift; + significand <<= shift; + significand |= (r >> (64 - shift)); + } + + /* + * Set the sticky bit, since there is almost surely another 1 + * in the bit stream. Otherwise, we might round what looks + * like a tie to even when, almost surely, were we to look + * further in the bit stream, there would be a 1 breaking the + * tie. + */ + significand |= 1; + + /* + * Finally, convert to double (rounding) and scale by + * 2^exponent. + */ + return ldexp((double)significand, exponent); +} +/* ====@@@@@=== */ diff --git a/Src/exec.c b/Src/exec.c index a473938ec..8aa7466f5 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -881,6 +881,10 @@ execute(LinkList args, int flags, int defpath) _realexit(); else zerr("command not found: %s", arg0); + /* This is bash behavior, but fails to restore interactive settings etc. + lastval = ((eno == EACCES || eno == ENOEXEC) ? 126 : 127); + return; + */ _exit((eno == EACCES || eno == ENOEXEC) ? 126 : 127); } @@ -1089,7 +1093,7 @@ entersubsh(int flags, struct entersubsh_ret *retp) int i, sig, monitor, job_control_ok; if (!(flags & ESUB_KEEPTRAP)) - for (sig = 0; sig < SIGCOUNT; sig++) + for (sig = 0; sig <= SIGCOUNT; sig++) if (!(sigtrapped[sig] & ZSIG_FUNC) && !(isset(POSIXTRAPS) && (sigtrapped[sig] & ZSIG_IGNORED))) unsettrap(sig); @@ -1203,7 +1207,7 @@ entersubsh(int flags, struct entersubsh_ret *retp) * Start loop at 1 because 0 is SIGEXIT */ if (intrap) - for (sig = 1; sig < SIGCOUNT; sig++) + for (sig = 1; sig <= SIGCOUNT; sig++) if (sigtrapped[sig] && sigtrapped[sig] != ZSIG_IGNORED) signal_unblock(signal_mask(sig)); if (!job_control_ok) @@ -1677,7 +1681,7 @@ execpline(Estate state, wordcode slcode, int how, int last1) wordcode code = *state->pc++; static int lastwj, lpforked; - if (wc_code(code) != WC_PIPE) + if (wc_code(code) != WC_PIPE && !(how & Z_TIMED)) return lastval = (slflags & WC_SUBLIST_NOT) != 0; else if (slflags & WC_SUBLIST_NOT) last1 = 0; @@ -2939,6 +2943,14 @@ execcmd_exec(Estate state, Execcmd_params eparams, */ LinkList preargs; + /* + * for the "time" keyword + */ + child_times_t shti, chti; + struct timeval then; + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 0); + doneps4 = 0; /* @@ -3071,6 +3083,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, if (!(hn = resolvebuiltin(cmdarg, hn))) { if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } if (type != WC_TYPESET) @@ -3252,6 +3266,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, errflag |= ERRFLAG_ERROR; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } } @@ -3343,6 +3359,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, errflag |= ERRFLAG_ERROR; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } else if (!nullcmd || !*nullcmd || opts[SHNULLCMD]) { if (!args) @@ -3363,6 +3381,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, lastval = 0; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } else { /* @@ -3375,6 +3395,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, lastval = 1; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } cmdoutval = use_cmdoutval ? lastval : 0; @@ -3393,6 +3415,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, } if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } } else if (isset(RESTRICTED) && (cflags & BINF_EXEC) && do_exec) { @@ -3401,6 +3425,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, lastval = 1; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } @@ -3437,6 +3463,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, opts[AUTOCONTINUE] = oautocont; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } break; @@ -3448,6 +3476,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, if (!(hn = resolvebuiltin(cmdarg, hn))) { if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } break; @@ -3466,6 +3496,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, opts[AUTOCONTINUE] = oautocont; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } @@ -3545,6 +3577,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, opts[AUTOCONTINUE] = oautocont; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } } @@ -3575,6 +3609,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, opts[AUTOCONTINUE] = oautocont; if (forked) _realexit(); + if (how & Z_TIMED) + shelltime(&shti, &chti, &then, 1); return; } @@ -4377,6 +4413,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, errflag |= ERRFLAG_ERROR; } } + if ((is_cursh || do_exec) && (how & Z_TIMED)) + shelltime(&shti, &chti, &then, 1); if (newxtrerr) { int eno = errno; fil = fileno(newxtrerr); @@ -4409,7 +4447,7 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p) while (wc_code(ac = *pc) == WC_ASSIGN) { s = ecrawstr(state->prog, pc + 1, NULL); if ((pm = (Param) paramtab->getnode(paramtab, s))) { - Param tpm; + Param tpm = NULL; if (pm->env) delenv(pm); if (!(pm->node.flags & PM_SPECIAL)) { @@ -4426,7 +4464,6 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p) tpm = (Param) zshcalloc(sizeof *tpm); tpm->node.nam = ztrdup(pm->node.nam); copyparam(tpm, pm, 0); - pm = tpm; } else if (!(pm->node.flags & PM_READONLY) && (unset(RESTRICTED) || !(pm->node.flags & PM_RESTRICTED))) { /* @@ -4437,10 +4474,10 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p) tpm = (Param) hcalloc(sizeof *tpm); tpm->node.nam = pm->node.nam; copyparam(tpm, pm, 1); - pm = tpm; } addlinknode(*remove_p, dupstring(s)); - addlinknode(*restore_p, pm); + if (tpm) + addlinknode(*restore_p, tpm); } else addlinknode(*remove_p, dupstring(s)); @@ -5266,7 +5303,7 @@ exectime(Estate state, UNUSED(int do_exec)) jb = thisjob; if (WC_TIMED_TYPE(state->pc[-1]) == WC_TIMED_EMPTY) { - shelltime(); + shelltime(NULL,NULL,NULL,0); return 0; } execpline(state, *state->pc++, Z_TIMED|Z_SYNC, 0); diff --git a/Src/init.c b/Src/init.c index ec21521b1..61f759ded 100644 --- a/Src/init.c +++ b/Src/init.c @@ -36,6 +36,10 @@ #include "version.h" +#if defined(HAVE_SYS_SYSCTL_H) && !defined(__linux) +#include <sys/sysctl.h> +#endif + /**/ int noexitct = 0; @@ -695,7 +699,6 @@ init_io(char *cmd) } else opts[USEZLE] = 0; -#ifdef JOB_CONTROL /* If interactive, make sure the shell is in the foreground and is the * process group leader. */ @@ -708,9 +711,6 @@ init_io(char *cmd) acquire_pgrp(); /* might also clear opts[MONITOR] */ } } -#else - opts[MONITOR] = 0; -#endif } /**/ @@ -718,7 +718,7 @@ mod_export void init_shout(void) { static char shoutbuf[BUFSIZ]; -#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC) +#if defined(TIOCSETD) && defined(NTTYDISC) int ldisc; #endif @@ -729,7 +729,7 @@ init_shout(void) return; } -#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC) +#if defined(TIOCSETD) && defined(NTTYDISC) ldisc = NTTYDISC; ioctl(SHTTY, TIOCSETD, (char *)&ldisc); #endif @@ -917,12 +917,6 @@ getmypath(const char *name, const char *cwd) char *buf; int namelen; - if (!name) - return NULL; - if (*name == '-') - ++name; - if ((namelen = strlen(name)) == 0) - return NULL; #if defined(__APPLE__) { uint32_t n = PATH_MAX; @@ -938,6 +932,19 @@ getmypath(const char *name, const char *cwd) else free(buf); } +#elif defined(KERN_PROC_PATHNAME) + { +#ifdef __NetBSD__ + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_PATHNAME }; +#else + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; +#endif + size_t len = PATH_MAX; + buf = (char *) zalloc(PATH_MAX); + if (!sysctl(mib, 4, buf, &len, NULL, 0) && len > 1) + return buf; + free(buf); + } #elif defined(PROC_SELF_EXE) { ssize_t n; @@ -951,6 +958,13 @@ getmypath(const char *name, const char *cwd) free(buf); } #endif + + if (!name) + return NULL; + if (*name == '-') + ++name; + if ((namelen = strlen(name)) == 0) + return NULL; /* guess the absolute pathname of 'name' */ if (name[namelen-1] == '/') /* name should not end with '/' */ return NULL; @@ -968,7 +982,7 @@ getmypath(const char *name, const char *cwd) } #ifdef HAVE_REALPATH else { - /* search each dir in PARH */ + /* search each dir in PATH */ const char *path, *sep; char *real, *try; int pathlen, dirlen; @@ -982,7 +996,7 @@ getmypath(const char *name, const char *cwd) do { sep = strchr(path, ':'); dirlen = sep ? sep - path : strlen(path); - strncpy(try, path, dirlen); + memcpy(try, path, dirlen); try[dirlen] = '/'; try[dirlen+1] = '\0'; strcat(try, name); @@ -1245,7 +1259,11 @@ setupvals(char *cmd, char *runscript, char *zsh_name) pwd = metafy(zgetcwd(), -1, META_DUP); } - oldpwd = ztrdup(pwd); /* initialize `OLDPWD' = `PWD' */ + oldpwd = zgetenv("OLDPWD"); + if (oldpwd == NULL) + oldpwd = ztrdup(pwd); /* initialize `OLDPWD' = `PWD' */ + else + oldpwd = ztrdup(oldpwd); inittyptab(); /* initialize the ztypes table */ initlextabs(); /* initialize lexing tables */ @@ -1382,6 +1400,8 @@ setupshin(char *runscript) void init_signals(void) { + struct sigaction act; + sigtrapped = (int *) hcalloc(TRAPCOUNT * sizeof(int)); siglists = (Eprog *) hcalloc(TRAPCOUNT * sizeof(Eprog)); @@ -1395,14 +1415,8 @@ init_signals(void) intr(); -#ifdef POSIX_SIGNALS - { - struct sigaction act; - if (!sigaction(SIGQUIT, NULL, &act) && - act.sa_handler == SIG_IGN) - sigtrapped[SIGQUIT] = ZSIG_IGNORED; - } -#endif + if (!sigaction(SIGQUIT, NULL, &act) && act.sa_handler == SIG_IGN) + sigtrapped[SIGQUIT] = ZSIG_IGNORED; #ifndef QDEBUG signal_ignore(SIGQUIT); diff --git a/Src/input.c b/Src/input.c index d8ac2c0e7..320fd6500 100644 --- a/Src/input.c +++ b/Src/input.c @@ -217,26 +217,23 @@ shinbufrestore(void) static int shingetchar(void) { - int nread, rsize = isset(SHINSTDIN) ? 1 : SHINBUFSIZE; + int nread; if (shinbufptr < shinbufendptr) return (unsigned char) *shinbufptr++; shinbufreset(); #ifdef USE_LSEEK - if (rsize == 1 && lseek(SHIN, 0, SEEK_CUR) != (off_t)-1) - rsize = SHINBUFSIZE; - if (rsize > 1) { + if (!isset(SHINSTDIN) || lseek(SHIN, 0, SEEK_CUR) != (off_t) -1) { do { errno = 0; - nread = read(SHIN, shinbuffer, rsize); + nread = read(SHIN, shinbuffer, SHINBUFSIZE); } while (nread < 0 && errno == EINTR); if (nread <= 0) return -1; if (isset(SHINSTDIN) && (shinbufendptr = memchr(shinbuffer, '\n', nread))) { - shinbufendptr++; - rsize = (shinbufendptr - shinbuffer); + int rsize = (++shinbufendptr - shinbuffer); if (nread > rsize && lseek(SHIN, -(nread - rsize), SEEK_CUR) < 0) zerr("lseek(%d, %d): %e", SHIN, -(nread - rsize), errno); diff --git a/Src/jobs.c b/Src/jobs.c index 07facc60b..39c664388 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -1894,7 +1894,7 @@ spawnjob(void) /**/ void -shelltime(void) +shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int delta) { struct timezone dummy_tz; struct timeval dtimeval, now; @@ -1913,7 +1913,28 @@ shelltime(void) ti.ut = buf.tms_utime; ti.st = buf.tms_stime; #endif - printtime(dtime(&dtimeval, &shtimer, &now), &ti, "shell"); + if (shell) { + if (delta) { +#ifdef HAVE_GETRUSAGE + dtime(&ti.ru_utime, &shell->ru_utime, &ti.ru_utime); + dtime(&ti.ru_stime, &shell->ru_stime, &ti.ru_stime); +#else + ti.ut -= shell->ut; + ti.st -= shell->st; +#endif + } else + *shell = ti; + } + if (delta) + dtime(&dtimeval, then, &now); + else { + if (then) + *then = now; + dtime(&dtimeval, &shtimer, &now); + } + + if (!delta == !shell) + printtime(&dtimeval, &ti, "shell"); #ifdef HAVE_GETRUSAGE getrusage(RUSAGE_CHILDREN, &ti); @@ -1921,8 +1942,20 @@ shelltime(void) ti.ut = buf.tms_cutime; ti.st = buf.tms_cstime; #endif - printtime(&dtimeval, &ti, "children"); - + if (kids) { + if (delta) { +#ifdef HAVE_GETRUSAGE + dtime(&ti.ru_utime, &kids->ru_utime, &ti.ru_utime); + dtime(&ti.ru_stime, &kids->ru_stime, &ti.ru_stime); +#else + ti.ut -= shell->ut; + ti.st -= shell->st; +#endif + } else + *kids = ti; + } + if (!delta == !kids) + printtime(&dtimeval, &ti, "children"); } /* see if jobs need printing */ diff --git a/Src/lex.c b/Src/lex.c index 700af2da1..efbb62b66 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1402,10 +1402,11 @@ gettokstr(int c, int sub) /* * Same logic as Dash, for ! to perform negation in range. */ - if (seen_brct) + if (seen_brct && brct) c = Bang; else c = '!'; + break; case LX2_OTHER: if (in_brace_param) { if (c == '/') { diff --git a/Src/loop.c b/Src/loop.c index 0f3847541..84dc66476 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -165,7 +165,7 @@ execfor(Estate state, int do_exec) fprintf(xtrerr, "%s=%s\n", name, str); fflush(xtrerr); } - setloopvar(name, ztrdup(str)); + setloopvar(name, str); count++; } if (!count) diff --git a/Src/options.c b/Src/options.c index a0e1aa024..8b37ab5e8 100644 --- a/Src/options.c +++ b/Src/options.c @@ -877,7 +877,6 @@ dosetopt(int optno, int value, int force, char *new_opts) } #endif /* HAVE_SETRESGID && HAVE_SETRESUID */ -#ifdef JOB_CONTROL } else if (!force && optno == MONITOR && value) { if (new_opts[optno] == value) return 0; @@ -887,14 +886,6 @@ dosetopt(int optno, int value, int force, char *new_opts) origpgrp = GETPGRP(); acquire_pgrp(); } -#else - } else if(optno == MONITOR && value) { - return -1; -#endif /* not JOB_CONTROL */ -#ifdef GETPWNAM_FAKED - } else if(optno == CDABLEVARS && value) { - return -1; -#endif /* GETPWNAM_FAKED */ } else if ((optno == EMACSMODE || optno == VIMODE) && value) { if (sticky && sticky->emulation) return -1; diff --git a/Src/params.c b/Src/params.c index f65aa1e80..acd577527 100644 --- a/Src/params.c +++ b/Src/params.c @@ -482,7 +482,8 @@ static initparam argvparam_pm = IPDEF9("", &pparams, NULL, \ #define GETREFNAME(PM) (((PM)->node.flags & PM_SPECIAL) ? \ (PM)->gsu.s->getfn(PM) : (PM)->u.str) #define SETREFNAME(PM,S) (((PM)->node.flags & PM_SPECIAL) ? \ - (PM)->gsu.s->setfn(PM,(S)) : ((PM)->u.str = (S))) + (PM)->gsu.s->setfn(PM,(S)) : \ + (zsfree((PM)->u.str), (PM)->u.str = (S))) static Param argvparam; @@ -2811,9 +2812,10 @@ assignstrvalue(Value v, char *val, int flags) break; } setscope(v->pm); - if ((!v->pm->env && !(v->pm->node.flags & PM_EXPORTED) && - !(isset(ALLEXPORT) && !(v->pm->node.flags & PM_HASHELEM))) || - (v->pm->node.flags & PM_ARRAY) || v->pm->ename) + if (errflag || + ((!v->pm->env && !(v->pm->node.flags & PM_EXPORTED) && + !(isset(ALLEXPORT) && !(v->pm->node.flags & PM_HASHELEM))) || + (v->pm->node.flags & PM_ARRAY) || v->pm->ename)) return; export_param(v->pm); } @@ -3790,7 +3792,7 @@ unsetparam_pm(Param pm, int altflag, int exp) altremove = NULL; pm->node.flags &= ~PM_DECLARED; /* like ksh, not like bash */ - if (!(pm->node.flags & PM_UNSET)) + if (!(pm->node.flags & PM_UNSET) || (pm->node.flags & PM_REMOVABLE)) pm->gsu.s->unsetfn(pm, exp); if (pm->env) delenv(pm); @@ -6330,9 +6332,10 @@ setloopvar(char *name, char *value) pm->node.flags &= ~PM_UNSET; pm->node.flags |= PM_NEWREF; setscope(pm); - pm->node.flags &= ~PM_NEWREF; + if (!errflag) + pm->node.flags &= ~PM_NEWREF; } else - setsparam(name, value); + setsparam(name, ztrdup(value)); } /**/ diff --git a/Src/signals.c b/Src/signals.c index d28853ea6..86f1a49f6 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -91,33 +91,6 @@ mod_export volatile int trap_queueing_enabled, trap_queue_front, trap_queue_rear /**/ mod_export int trap_queue[MAX_QUEUE_SIZE]; -/* This is only used on machines that don't understand signal sets. * - * On SYSV machines this will represent the signals that are blocked * - * (held) using sighold. On machines which can't block signals at * - * all, we will simulate this by ignoring them and remembering them * - * in this variable. */ -#if !defined(POSIX_SIGNALS) && !defined(BSD_SIGNALS) -static sigset_t blocked_set; -#endif - -#ifdef POSIX_SIGNALS -# define signal_jmp_buf sigjmp_buf -# define signal_setjmp(b) sigsetjmp((b),1) -# define signal_longjmp(b,n) siglongjmp((b),(n)) -#else -# define signal_jmp_buf jmp_buf -# define signal_setjmp(b) setjmp(b) -# define signal_longjmp(b,n) longjmp((b),(n)) -#endif - -#ifdef NO_SIGNAL_BLOCKING -# define signal_process(sig) signal_ignore(sig) -# define signal_reset(sig) install_handler(sig) -#else -# define signal_process(sig) ; -# define signal_reset(sig) ; -#endif - /* Install signal handler for given signal. * * If possible, we want to make sure that interrupted * * system calls are not restarted. */ @@ -126,10 +99,9 @@ static sigset_t blocked_set; mod_export void install_handler(int sig) { -#ifdef POSIX_SIGNALS struct sigaction act; - act.sa_handler = (SIGNAL_HANDTYPE) zhandler; + act.sa_handler = (void (*)(int)) zhandler; sigemptyset(&act.sa_mask); /* only block sig while in handler */ act.sa_flags = 0; # ifdef SA_INTERRUPT /* SunOS 4.x */ @@ -137,27 +109,6 @@ install_handler(int sig) act.sa_flags |= SA_INTERRUPT; /* make sure system calls are not restarted */ # endif sigaction(sig, &act, (struct sigaction *)NULL); -#else -# ifdef BSD_SIGNALS - struct sigvec vec; - - vec.sv_handler = (SIGNAL_HANDTYPE) zhandler; - vec.sv_mask = sigmask(sig); /* mask out this signal while in handler */ -# ifdef SV_INTERRUPT - vec.sv_flags = SV_INTERRUPT; /* make sure system calls are not restarted */ -# endif - sigvec(sig, &vec, (struct sigvec *)NULL); -# else -# ifdef SYSV_SIGNALS - /* we want sigset rather than signal because it will * - * block sig while in handler. signal usually doesn't */ - sigset(sig, zhandler); -# else /* NO_SIGNAL_BLOCKING (bummer) */ - signal(sig, zhandler); - -# endif /* SYSV_SIGNALS */ -# endif /* BSD_SIGNALS */ -#endif /* POSIX_SIGNALS */ } /* enable ^C interrupts */ @@ -220,49 +171,16 @@ signal_mask(int sig) * set. Return the old signal set. */ /**/ -#ifndef BSD_SIGNALS - -/**/ mod_export sigset_t signal_block(sigset_t set) { sigset_t oset; -#ifdef POSIX_SIGNALS sigprocmask(SIG_BLOCK, &set, &oset); -#else -# ifdef SYSV_SIGNALS - int i; - - oset = blocked_set; - for (i = 1; i <= NSIG; ++i) { - if (sigismember(&set, i) && !sigismember(&blocked_set, i)) { - sigaddset(&blocked_set, i); - sighold(i); - } - } -# else /* NO_SIGNAL_BLOCKING */ -/* We will just ignore signals if the system doesn't have * - * the ability to block them. */ - int i; - - oset = blocked_set; - for (i = 1; i <= NSIG; ++i) { - if (sigismember(&set, i) && !sigismember(&blocked_set, i)) { - sigaddset(&blocked_set, i); - signal_ignore(i); - } - } -# endif /* SYSV_SIGNALS */ -#endif /* POSIX_SIGNALS */ - return oset; } -/**/ -#endif /* BSD_SIGNALS */ - /* Unblock the signals in the given signal * * set. Return the old signal set. */ @@ -272,39 +190,7 @@ signal_unblock(sigset_t set) { sigset_t oset; -#ifdef POSIX_SIGNALS sigprocmask(SIG_UNBLOCK, &set, &oset); -#else -# ifdef BSD_SIGNALS - sigfillset(&oset); - oset = sigsetmask(oset); - sigsetmask(oset & ~set); -# else -# ifdef SYSV_SIGNALS - int i; - - oset = blocked_set; - for (i = 1; i <= NSIG; ++i) { - if (sigismember(&set, i) && sigismember(&blocked_set, i)) { - sigdelset(&blocked_set, i); - sigrelse(i); - } - } -# else /* NO_SIGNAL_BLOCKING */ -/* On systems that can't block signals, we are just ignoring them. So * - * to unblock signals, we just reenable the signal handler for them. */ - int i; - - oset = blocked_set; - for (i = 1; i <= NSIG; ++i) { - if (sigismember(&set, i) && sigismember(&blocked_set, i)) { - sigdelset(&blocked_set, i); - install_handler(i); - } - } -# endif /* SYSV_SIGNALS */ -# endif /* BSD_SIGNALS */ -#endif /* POSIX_SIGNALS */ return oset; } @@ -318,61 +204,18 @@ signal_setmask(sigset_t set) { sigset_t oset; -#ifdef POSIX_SIGNALS sigprocmask(SIG_SETMASK, &set, &oset); -#else -# ifdef BSD_SIGNALS - oset = sigsetmask(set); -# else -# ifdef SYSV_SIGNALS - int i; - - oset = blocked_set; - for (i = 1; i <= NSIG; ++i) { - if (sigismember(&set, i) && !sigismember(&blocked_set, i)) { - sigaddset(&blocked_set, i); - sighold(i); - } else if (!sigismember(&set, i) && sigismember(&blocked_set, i)) { - sigdelset(&blocked_set, i); - sigrelse(i); - } - } -# else /* NO_SIGNAL_BLOCKING */ - int i; - - oset = blocked_set; - for (i = 1; i < NSIG; ++i) { - if (sigismember(&set, i) && !sigismember(&blocked_set, i)) { - sigaddset(&blocked_set, i); - signal_ignore(i); - } else if (!sigismember(&set, i) && sigismember(&blocked_set, i)) { - sigdelset(&blocked_set, i); - install_handler(i); - } - } -# endif /* SYSV_SIGNALS */ -# endif /* BSD_SIGNALS */ -#endif /* POSIX_SIGNALS */ return oset; } -#if defined(NO_SIGNAL_BLOCKING) -static int suspend_longjmp = 0; -static signal_jmp_buf suspend_jmp_buf; -#endif - /**/ int signal_suspend(UNUSED(int sig), int wait_cmd) { int ret; -#if defined(POSIX_SIGNALS) || defined(BSD_SIGNALS) sigset_t set; -# if defined(POSIX_SIGNALS) && defined(BROKEN_POSIX_SIGSUSPEND) - sigset_t oset; -# endif sigemptyset(&set); @@ -384,36 +227,8 @@ signal_suspend(UNUSED(int sig), int wait_cmd) if (!(wait_cmd || isset(TRAPSASYNC) || (sigtrapped[SIGINT] & ~ZSIG_IGNORED))) sigaddset(&set, SIGINT); -#endif /* POSIX_SIGNALS || BSD_SIGNALS */ -#ifdef POSIX_SIGNALS -# ifdef BROKEN_POSIX_SIGSUSPEND - sigprocmask(SIG_SETMASK, &set, &oset); - ret = pause(); - sigprocmask(SIG_SETMASK, &oset, NULL); -# else /* not BROKEN_POSIX_SIGSUSPEND */ ret = sigsuspend(&set); -# endif /* BROKEN_POSIX_SIGSUSPEND */ -#else /* not POSIX_SIGNALS */ -# ifdef BSD_SIGNALS - ret = sigpause(set); -# else -# ifdef SYSV_SIGNALS - ret = sigpause(sig); - -# else /* NO_SIGNAL_BLOCKING */ - /* need to use signal_longjmp to make this race-free * - * between the child_unblock() and pause() */ - if (signal_setjmp(suspend_jmp_buf) == 0) { - suspend_longjmp = 1; /* we want to signal_longjmp after catching signal */ - child_unblock(); /* do we need to do wait_cmd stuff as well? */ - ret = pause(); - } - suspend_longjmp = 0; /* turn off using signal_longjmp since we are past * - * the pause() function. */ -# endif /* SYSV_SIGNALS */ -# endif /* BSD_SIGNALS */ -#endif /* POSIX_SIGNALS */ return ret; } @@ -586,33 +401,12 @@ zhandler(int sig) { sigset_t newmask, oldmask; -#if defined(NO_SIGNAL_BLOCKING) - int do_jump; - signal_jmp_buf jump_to; -#endif - last_signal = sig; - signal_process(sig); sigfillset(&newmask); /* Block all signals temporarily */ oldmask = signal_block(newmask); -#if defined(NO_SIGNAL_BLOCKING) - /* do we need to longjmp to signal_suspend */ - do_jump = suspend_longjmp; - /* In case a SIGCHLD somehow arrives */ - suspend_longjmp = 0; - - /* Traps can cause nested signal_suspend() */ - if (sig == SIGCHLD) { - if (do_jump) { - /* Copy suspend_jmp_buf */ - jump_to = suspend_jmp_buf; - } - } -#endif - /* Are we queueing signals now? */ if (queueing_enabled) { int temp_rear = ++queue_rear % MAX_QUEUE_SIZE; @@ -627,7 +421,6 @@ zhandler(int sig) /* save current signal mask */ signal_mask_queue[queue_rear] = oldmask; } - signal_reset(sig); return; } @@ -704,14 +497,6 @@ zhandler(int sig) break; } /* end of switch(sig) */ - signal_reset(sig); - -/* This is used to make signal_suspend() race-free */ -#if defined(NO_SIGNAL_BLOCKING) - if (do_jump) - signal_longjmp(jump_to, 1); -#endif - } /* handler */ diff --git a/Src/signals.h b/Src/signals.h index 7910f6b79..0540d4b0b 100644 --- a/Src/signals.h +++ b/Src/signals.h @@ -27,8 +27,6 @@ * */ -#define SIGNAL_HANDTYPE void (*)(int) - #ifndef HAVE_KILLPG # define killpg(pgrp,sig) kill(-(pgrp),sig) #endif @@ -51,20 +49,6 @@ # define SV_INTERRUPT SV_BSDSIG #endif -/* If not a POSIX machine, then we create our * - * own POSIX style signal sets functions. */ -#ifndef POSIX_SIGNALS -# define sigemptyset(s) (*(s) = 0) -# if NSIG == 32 -# define sigfillset(s) (*(s) = ~(sigset_t)0, 0) -# else -# define sigfillset(s) (*(s) = (1 << NSIG) - 1, 0) -# endif -# define sigaddset(s,n) (*(s) |= (1 << ((n) - 1)), 0) -# define sigdelset(s,n) (*(s) &= ~(1 << ((n) - 1)), 0) -# define sigismember(s,n) ((*(s) & (1 << ((n) - 1))) != 0) -#endif /* ifndef POSIX_SIGNALS */ - #define child_block() signal_block(sigchld_mask) #define child_unblock() signal_unblock(sigchld_mask) @@ -142,10 +126,5 @@ #define queue_signal_level() queueing_enabled -#ifdef BSD_SIGNALS -#define signal_block(S) sigblock(S) -#else extern sigset_t signal_block (sigset_t); -#endif /* BSD_SIGNALS */ - extern sigset_t signal_unblock (sigset_t); diff --git a/Src/zsh_system.h b/Src/zsh_system.h index 5c004d53e..21446a9b1 100644 --- a/Src/zsh_system.h +++ b/Src/zsh_system.h @@ -369,8 +369,6 @@ struct timespec { # ifndef TIME_H_SELECT_H_CONFLICTS # include <sys/select.h> # endif -#elif defined(SELECT_IN_SYS_SOCKET_H) -# include <sys/socket.h> #endif #if defined(__APPLE__) && defined(HAVE_SELECT) @@ -803,16 +801,6 @@ extern short ospeed; #endif #endif -/* Can't support job control without working tcsetgrp() */ -#ifdef BROKEN_TCSETPGRP -#undef JOB_CONTROL -#endif /* BROKEN_TCSETPGRP */ - -#ifdef BROKEN_KILL_ESRCH -#undef ESRCH -#define ESRCH EINVAL -#endif /* BROKEN_KILL_ESRCH */ - /* Can we do locale stuff? */ #undef USE_LOCALE #if defined(CONFIG_LOCALE) && defined(HAVE_SETLOCALE) && defined(LC_ALL) diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst index d57085798..660602caf 100644 --- a/Test/A01grammar.ztst +++ b/Test/A01grammar.ztst @@ -399,13 +399,6 @@ >This is name2 >This is still name2 - (time cat) >&/dev/null -0:`time' keyword (status only) - - TIMEFMT='%E %mE %uE %* %m%mm %u%uu'; time (:) -0:`time' keyword with custom TIMEFMT -*?[0-9]##.[0-9](#c2)s [0-9]##ms [0-9]##us %\* %m%mm %u%uu - if [[ -f foo && -d . && -n $ZTST_testdir ]]; then true else diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst index 3eff5331a..9f779b9a8 100644 --- a/Test/A06assign.ztst +++ b/Test/A06assign.ztst @@ -743,3 +743,10 @@ print $a 0:overwrite [2] character (string: "") with "xx" >xx + + ( sleep 1 & + x[1]=$! + typeset -p x + ) +0:regression workers/53033: assigning $! to array element +*>typeset -g -a x=\( <-> \) diff --git a/Test/A08time.ztst b/Test/A08time.ztst new file mode 100644 index 000000000..22a460f5e --- /dev/null +++ b/Test/A08time.ztst @@ -0,0 +1,65 @@ +# +# This file contains tests for the "time" reserved word +# + +%prep + + unset TIMEFMT + +%test + + (time cat) >&/dev/null +0:`time' keyword (status only) + + ( TIMEFMT='%E %mE %uE %* %m%mm %u%uu'; time (:) ) +0:`time' keyword with custom TIMEFMT +*?[0-9]##.[0-9](#c2)s [0-9]##ms [0-9]##us %\* %m%mm %u%uu + + time x=1 +0:`time' simple assignment +*?shell* +*?children* + + time x=$(date) +0:`time' assignment with external command +*?shell* +*?children* + + x=0; time for ((i=1; i<=10000; ++i)); do ((x+=i)); done; echo $x +0:`time' for-loop with arithmetic condition +>50005000 +*?shell* +*?children* + + time echo $(x=0;for ((i=0; i<=100000; ++i)); do ((x+=i)); done; echo $x) +0:`time' of a builtin with argument command substitution +>5000050000 +*?shell* +*?children* + + time cat <(x=0;for ((i=0; i<=100000; ++i)); do ((x+=i)); done; echo $x) +0:`time' of external command with process substitution +>5000050000 +*?*user*system*cpu*total + + print -u $ZTST_fd 'This test takes 2 seconds' + time builtin nonesuch $(sleep 2) +1:`time' of nonexistent builtin with command substitution +*?*: no such builtin: nonesuch +*?shell* +*?children* + + time /no/such/commmand +127:`time' of nonexistent external +*?*no such file or directory: /no/such/commmand +*?*user*system*cpu*total + + ( setopt errexit; time false; print notreached ) +1:`time' of failed builtin with errexit +*?shell* +*?children* + + ( setopt errexit; time expr 0; print notreached ) +1:`time' of failed external with errexit +>0 +*?*user*system*cpu*total diff --git a/Test/X05zleincarg.ztst b/Test/X05zleincarg.ztst index cd9817c82..f712e9426 100644 --- a/Test/X05zleincarg.ztst +++ b/Test/X05zleincarg.ztst @@ -5,29 +5,29 @@ if ( zmodload zsh/zpty 2>/dev/null ); then . $ZTST_srcdir/comptest comptestinit -v -z $ZTST_testdir/../Src/zsh + zpty_run ' + autoload -Uz incarg + for name in {,vim-,vim-backward-}{,sync-}{inc,dec}arg; do + zle -N "$name" incarg + done + bindkey -v "^N" incarg + bindkey -v "^P" decarg + bindkey -v "^F" sync-incarg + bindkey -v "^B" sync-decarg + bindkey -a "^N" vim-incarg + bindkey -a "^P" vim-decarg + bindkey -a "^F" vim-sync-incarg + bindkey -a "^B" vim-sync-decarg + bindkey -a "^E" vim-backward-incarg + bindkey -a "^Y" vim-backward-decarg + unset TMUX_PANE ITERM_SESSION_ID + tmux() { + echo "$TMUX_PANE" + } + ' else ZTST_unimplemented="the zsh/zpty module is not available" fi - zpty_run ' - autoload -Uz incarg - for name in {,vim-,vim-backward-}{,sync-}{inc,dec}arg; do - zle -N "$name" incarg - done - bindkey -v "^N" incarg - bindkey -v "^P" decarg - bindkey -v "^F" sync-incarg - bindkey -v "^B" sync-decarg - bindkey -a "^N" vim-incarg - bindkey -a "^P" vim-decarg - bindkey -a "^F" vim-sync-incarg - bindkey -a "^B" vim-sync-decarg - bindkey -a "^E" vim-backward-incarg - bindkey -a "^Y" vim-backward-decarg - unset TMUX_PANE ITERM_SESSION_ID - tmux() { - echo "$TMUX_PANE" - } - ' %test diff --git a/configure.ac b/configure.ac index 78621042d..bca99b7f8 100644 --- a/configure.ac +++ b/configure.ac @@ -634,8 +634,9 @@ if test "x$enable_pcre" = xyes; then fi AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \ - termios.h sys/param.h sys/filio.h string.h memory.h \ + termios.h sys/param.h sys/filio.h \ limits.h fcntl.h libc.h sys/utsname.h sys/resource.h \ + sys/sysctl.h sys/random.h \ locale.h errno.h stdio.h stdarg.h varargs.h stdlib.h \ unistd.h sys/capability.h \ utmp.h utmpx.h sys/types.h pwd.h grp.h poll.h sys/mman.h \ @@ -848,11 +849,6 @@ esac]) AC_SEARCH_LIBS(getpwnam, nsl) -dnl I am told that told that unicos reqire these for nis_list -if test `echo $host_os | sed 's/^\(unicos\).*/\1/'` = unicos; then - LIBS="-lcraylm -lkrb -lnisdb -lnsl -lrpcsvc $LIBS" -fi - if test "x$dynamic" = xyes; then AC_CHECK_LIB(dl, dlopen) fi @@ -1257,13 +1253,12 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ fpurge fseeko ftello \ mkfifo _mktemp mkstemp \ waitpid wait3 \ - sigaction sigblock sighold sigrelse sigsetmask sigprocmask \ sigqueue \ killpg setpgid setpgrp tcsetpgrp tcgetattr nice \ gethostname gethostbyname2 getipnodebyname \ inet_aton inet_pton inet_ntop \ getlogin getpwent getpwnam getpwuid getgrgid getgrnam \ - initgroups nis_list \ + initgroups \ setuid seteuid setreuid setresuid setsid \ setgid setegid setregid setresgid \ memcpy memmove strstr strerror strtoul \ @@ -1274,7 +1269,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ signgam tgamma \ log2 \ scalbn \ - putenv getenv setenv unsetenv xw\ + putenv getenv setenv unsetenv \ brk sbrk \ pathconf sysconf \ tgetent tigetflag tigetnum tigetstr setupterm initscr resize_term \ @@ -1292,6 +1287,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ cygwin_conv_path \ nanosleep \ srand_deterministic \ + getrandom arc4random_buf \ setutxent getutxent endutxent getutent) AC_FUNC_STRCOLL @@ -1481,35 +1477,6 @@ case $host_os in darwin1[0-5]*) AC_DEFINE(SETENV_MANGLES_EQUAL) ;; esac -dnl ------------- -dnl CHECK SIGNALS -dnl ------------- -dnl What style of signal do you have (POSIX, BSD, or SYSV)? -AH_TEMPLATE([POSIX_SIGNALS], -[Define to 1 if you use POSIX style signal handling.]) -AH_TEMPLATE([BSD_SIGNALS], -[Define to 1 if you use BSD style signal handling (and can block signals).]) -AH_TEMPLATE([SYSV_SIGNALS], -[Define to 1 if you use SYS style signal handling (and can block signals).]) -AH_TEMPLATE([NO_SIGNAL_BLOCKING], -[Define to 1 if you have no signal blocking at all (bummer).]) -AC_MSG_CHECKING(what style of signals to use) -if test x$ac_cv_func_sigaction = xyes && test x$ac_cv_func_sigprocmask = xyes; then - signals_style=POSIX_SIGNALS - AC_DEFINE(POSIX_SIGNALS) -elif test x$ac_cv_func_sigblock = xyes && test x$ac_cv_func_sigsetmask = xyes; then - signals_style=BSD_SIGNALS - AC_DEFINE(BSD_SIGNALS) -elif test x$ac_cv_func_sighold = xyes && test x$ac_cv_func_sigrelse = xyes; then - signals_style=SYSV_SIGNALS - AC_DEFINE(SYSV_SIGNALS) -else - signals_style=NO_SIGNAL_BLOCKING - AC_DEFINE(NO_SIGNAL_BLOCKING) -fi -AC_DEFINE_UNQUOTED($signals_style) -AC_MSG_RESULT($signals_style) - dnl Where is <signal.h> located? Needed as input for signals.awk AC_CACHE_CHECK(where signal.h is located, zsh_cv_path_signal_h, [dnl Look at the output from the preprocessor. @@ -1906,6 +1873,7 @@ zsh_LIMIT_PRESENT(RLIMIT_NPTS) zsh_LIMIT_PRESENT(RLIMIT_SWAP) zsh_LIMIT_PRESENT(RLIMIT_KQUEUES) zsh_LIMIT_PRESENT(RLIMIT_UMTXP) +zsh_LIMIT_PRESENT(RLIMIT_NOVMON) zsh_LIMITS_EQUAL(VMEM, vmem, RSS, rss) zsh_LIMITS_EQUAL(VMEM, vmem, AS, as) @@ -1975,7 +1943,7 @@ AH_TEMPLATE([PATH_DEV_FD], [Define to the path of the /dev/fd filesystem.]) AC_CACHE_CHECK(for /dev/fd filesystem, zsh_cv_sys_path_dev_fd, [for zsh_cv_sys_path_dev_fd in /proc/self/fd /dev/fd no; do - (exec 3<&0; test -e $zsh_cv_sys_path_dev_fd/3;) && break + test x`echo ok|(cat $zsh_cv_sys_path_dev_fd/3 3<&0 2>/dev/null;)` = xok && break done]) if test x$zsh_cv_sys_path_dev_fd != xno; then AC_DEFINE_UNQUOTED(PATH_DEV_FD, "$zsh_cv_sys_path_dev_fd") @@ -2146,20 +2114,6 @@ if test x$zsh_cv_header_sys_ioctl_h_ioctl_proto = xyes; then AC_DEFINE(IOCTL_IN_SYS_IOCTL) fi -dnl ------------------- -dnl select() defined in <sys/socket.h>, ie BeOS R4.51 -dnl ------------------- -AH_TEMPLATE([SELECT_IN_SYS_SOCKET_H], -[Define to 1 if select() is defined in <sys/socket.h>, ie BeOS R4.51]) -if test x$ac_cv_header_sys_select_h != xyes; then - AC_CACHE_CHECK(for select() in <sys/socket.h>, - zsh_cv_header_socket_h_select_proto, - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], [[fd_set fd;]])],[zsh_cv_header_socket_h_select_proto=yes],[zsh_cv_header_socket_h_select_proto=no])]) - if test x$zsh_cv_header_socket_h_select_proto = xyes; then - AC_DEFINE(SELECT_IN_SYS_SOCKET_H) - fi -fi - dnl ----------- dnl named FIFOs dnl ----------- @@ -2293,156 +2247,6 @@ if test x$zsh_cv_sys_link = xyes; then AC_DEFINE(HAVE_LINK) fi -dnl ----------- -dnl test for whether kill(pid, 0) where pid doesn't exit -dnl should set errno to ESRCH, but some like BeOS R4.51 set to EINVAL -dnl ----------- -AC_CACHE_CHECK(if kill(pid, 0) returns ESRCH correctly, -zsh_cv_sys_killesrch, -[AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <unistd.h> -#include <signal.h> -#include <errno.h> -int main() -{ - int pid = (getpid() + 10000) & 0xffffff; - while (pid && (kill(pid, 0) == 0 || errno != ESRCH)) pid >>= 1; - return(errno!=ESRCH); -} -]])],[zsh_cv_sys_killesrch=yes],[zsh_cv_sys_killesrch=no],[zsh_cv_sys_killesrch=yes])]) -AH_TEMPLATE([BROKEN_KILL_ESRCH], -[Define to 1 if kill(pid, 0) doesn't return ESRCH, ie BeOS R4.51.]) -if test x$zsh_cv_sys_killesrch = xno; then - AC_DEFINE(BROKEN_KILL_ESRCH) -fi - -dnl ----------- -dnl if POSIX, test for working sigsuspend(). -dnl for instance, BeOS R4.51 is broken. -dnl ----------- -AH_TEMPLATE([BROKEN_POSIX_SIGSUSPEND], -Define to 1 if sigsuspend() is broken, ie BeOS R4.51.]) -if test x$signals_style = xPOSIX_SIGNALS; then - AC_CACHE_CHECK(if POSIX sigsuspend() works, - zsh_cv_sys_sigsuspend, - [AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <signal.h> -#include <unistd.h> -int child=0; -void handler(sig) - int sig; -{if(sig==SIGCHLD) child=1;} -int main() { - struct sigaction act; - sigset_t set; - int pid, ret; - act.sa_handler = &handler; - sigfillset(&act.sa_mask); - act.sa_flags = 0; - sigaction(SIGCHLD, &act, 0); - sigfillset(&set); - sigprocmask(SIG_SETMASK, &set, 0); - pid=fork(); - if(pid==0) return 0; - if(pid>0) { - sigemptyset(&set); - ret=sigsuspend(&set); - return(child==0); - } -} -]])],[zsh_cv_sys_sigsuspend=yes],[zsh_cv_sys_sigsuspend=no],[zsh_cv_sys_sigsuspend=yes])]) - if test x$zsh_cv_sys_sigsuspend = xno; then - AC_DEFINE(BROKEN_POSIX_SIGSUSPEND) - fi -fi - -dnl ----------- -dnl if found tcsetpgrp, test to see if it actually works -dnl for instance, BeOS R4.51 does not support it yet -dnl ----------- -AH_TEMPLATE([BROKEN_TCSETPGRP], -[Define to 1 if tcsetpgrp() doesn't work, ie BeOS R4.51.]) -AC_ARG_WITH(tcsetpgrp, -AS_HELP_STRING([--with-tcsetpgrp],[assumes that tcsetpgrp() exists and works correctly]),[ -case "x$withval" in - xyes) zsh_working_tcsetpgrp=yes;; - xno) zsh_working_tcsetpgrp=no;; - *) AC_MSG_ERROR(please use --with-tcsetpgrp=yes or --with-tcsetpgrp=no);; -esac],[zsh_working_tcsetpgrp=check]) -if test "x$ac_cv_func_tcsetpgrp" = xyes; then -case "x$zsh_working_tcsetpgrp" in - xcheck) - trap "" TTOU > /dev/null 2>&1 || : - AC_CACHE_CHECK(if tcsetpgrp() actually works, - zsh_cv_sys_tcsetpgrp, - [AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <sys/types.h> -#include <unistd.h> -#include <fcntl.h> -int main() { - int fd; - int ret; - fd=open("/dev/tty", O_RDWR); - if (fd < 0) return(2); - ret=tcsetpgrp(fd, tcgetpgrp(fd)); - if (ret < 0) return(1); - return(0); -} -]])],[zsh_cv_sys_tcsetpgrp=yes],[ -case $? in - 1) zsh_cv_sys_tcsetpgrp=no;; - 2) zsh_cv_sys_tcsetpgrp=notty;; - *) zsh_cv_sys_tcsetpgrp=error;; -esac - ],[zsh_cv_sys_tcsetpgrp=yes])]) - case "x$zsh_cv_sys_tcsetpgrp" in - xno) AC_DEFINE(BROKEN_TCSETPGRP);; - xyes) :;; - xnotty) AC_MSG_ERROR([no controlling tty -Try running configure with --with-tcsetpgrp or --without-tcsetpgrp]);; - *) AC_MSG_ERROR([unexpected return status]);; - esac - trap - TTOU > /dev/null 2>&1 || : - ;; - xyes) :;; - xno) AC_DEFINE(BROKEN_TCSETPGRP);; - *) AC_MSG_ERROR([unexpected value zsh_working_tcsetpgrp=$zsh_working_tcsetpgrp]);; -esac -fi - -dnl ----------- -dnl test for faked getpwnam() entry, ie a single entry returned for any username -dnl for instance, BeOS R4.51 is not multiuser yet, and fakes getpwnam() -dnl test by looking up two usernames that shouldn't succeed, and compare entry -dnl ----------- -AH_TEMPLATE([GETPWNAM_FAKED], -[Define to 1 if getpwnam() is faked, ie BeOS R4.51.]) -if test x$ac_cv_func_getpwnam = xyes; then - AC_CACHE_CHECK(if getpwnam() is faked, - zsh_cv_sys_getpwnam_faked, - [AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include <pwd.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -int main() { - struct passwd *pw1, *pw2; - char buf[1024], name[1024]; - sprintf(buf, "%d:%d", getpid(), rand()); - pw1=getpwnam(buf); - if (pw1) strcpy(name, pw1->pw_name); - sprintf(buf, "%d:%d", rand(), getpid()); - pw2=getpwnam(buf); - return(pw1!=0 && pw2!=0 && !strcmp(name, pw2->pw_name)); -} -]])],[zsh_cv_sys_getpwnam_faked=no],[zsh_cv_sys_getpwnam_faked=yes],[zsh_cv_sys_getpwnam_faked=no])]) - if test x$zsh_cv_sys_getpwnam_faked = xyes; then - AC_DEFINE(GETPWNAM_FAKED) - fi -fi - - dnl --------------- dnl check for the type of third argument of accept dnl --------------- @@ -2828,13 +2632,15 @@ int main(int argc, char *argv[]) fi case "$host_os" in osf*) DLLDFLAGS="${DLLDFLAGS=-shared -expect_unresolved '*'}" ;; - *freebsd*|*netbsd*|linux*|irix*|gnu*|interix*|dragonfly*) DLLDFLAGS="${DLLDFLAGS=-shared}" ;; + *freebsd*|*netbsd*|linux*|irix*|gnu*|interix*|dragonfly*|haiku*) DLLDFLAGS="${DLLDFLAGS=-shared}" ;; sunos*) DLLDFLAGS="${DLLDFLAGS=-assert nodefinitions}" ;; sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G $ldflags}" ;; aix*) DLLDFLAGS="${DLLDFLAGS=-G -bexpall -lc}" ;; solaris*|sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G}" ;; - darwin*) DLLDFLAGS="${DLLDFLAGS=-bundle -flat_namespace -undefined suppress}" ;; - beos*|haiku*) DLLDFLAGS="${DLLDFLAGS=-nostart}" ;; + darwin[[0-9]].*|darwin1?.*|darwin2[01].*) + DLLDFLAGS="${DLLDFLAGS=-bundle -flat_namespace -undefined suppress}" ;; + darwin*) DLLDFLAGS="${DLLDFLAGS=-bundle -flat_namespace -undefined dynamic_lookup}" ;; + beos*) DLLDFLAGS="${DLLDFLAGS=-nostart}" ;; openbsd*) if test x$zsh_cv_sys_elf = xyes; then DLLDFLAGS="${DLLDFLAGS=-shared -fPIC}" @@ -3173,16 +2979,6 @@ AH_TOP([/***** begin user configuration section *****/ /* Define this to be the location of your password file */ #define PASSWD_FILE "/etc/passwd" -/* Define this to be the name of your NIS/YP password * - * map (if applicable) */ -#define PASSWD_MAP "passwd.byname" - -/* Define to 1 if you want user names to be cached */ -#define CACHE_USERNAMES 1 - -/* Define to 1 if system supports job control */ -#define JOB_CONTROL 1 - /* Define this if you use "suspended" instead of "stopped" */ #define USE_SUSPENDED 1 |