mirror of
https://github.com/notwa/rc
synced 2024-12-21 21:49:40 -08:00
98 lines
3.7 KiB
Bash
Executable file
98 lines
3.7 KiB
Bash
Executable file
#!/usr/bin/env sh
|
|
# compat: +ash +bash +dash +hush +ksh +mksh +oksh +osh +posh +yash +zsh
|
|
|
|
__permit_hex() {
|
|
if xxd -l 0 2>/dev/null; then
|
|
__permit_hex() { exec xxd -p -l4 -- "$@"; }
|
|
else
|
|
__permit_hex() { exec hexdump -ve '1 1 "%02x"' -n4 -- "$@"; }
|
|
fi
|
|
__permit_hex "$@"
|
|
}
|
|
|
|
permit() { ### @- conditionally set executable permissions on each of its arguments.
|
|
### flags:
|
|
### * `-a` -- automatic: skip any files whose contents do not begin with
|
|
### with one of several signatures. this does not affect directories.
|
|
### * `-m` -- manual: turn off automatic mode. (default)
|
|
### * `-e` -- everything: consider both regular files and directories. (default)
|
|
### * `-f` -- files: skip any arguments that are not regular files.
|
|
### * `-d` -- directories: skip any arguments that are not directories.
|
|
### * `-n` -- dry-run: don't actually change anything.
|
|
### * `-v` -- verbose: print changes before doing them.
|
|
###
|
|
### the `-e`, `-f`, and `-d` flags all override one another, and any of them
|
|
### can be combined with `-a`. arguments that are neither regular files nor
|
|
### directories (such as symlinks) are always skipped. arguments that are
|
|
### already executable by the current user are skipped. arguments that do
|
|
### not appear to refer to an existing file are passed through to chmod.
|
|
### directories are never recursed.
|
|
unset __permit_4 __permit_a __permit_f __permit_h __permit_m __permit_n __permit_v __permit_x || return
|
|
|
|
__permit_h="[-v] [-n] [-a | -m] [-e | -f | -d] [--] {files...}"
|
|
if [ $# = 0 ]; then
|
|
printf >&2 'usage: permit %s\n' "$__permit_h"
|
|
return 64;
|
|
fi
|
|
|
|
__permit_v=0 # verbosity
|
|
__permit_n=0 # dry-run
|
|
__permit_m=e # mode
|
|
__permit_a=0 # automatic
|
|
|
|
unset __permit_stop || return
|
|
for __permit_f; do
|
|
shift
|
|
case "${__permit_stop+:}$__permit_f" in
|
|
(/\?|-h|-help|--help)
|
|
printf 'usage: permit %s\n' "$__permit_h"
|
|
return 0;;
|
|
(--) __permit_stop=1;;
|
|
(-?*)
|
|
while __permit_f="${__permit_f#?}"; [ -n "$__permit_f" ]; do
|
|
case "${__permit_f}" in
|
|
|
|
(v*) __permit_v=1;; # verbosity
|
|
(n*) __permit_n=1;; # dry-run
|
|
(a*) __permit_a=1;; # automatic
|
|
(m*) __permit_a=0;; # manual
|
|
(e*) __permit_m=e;; # everything
|
|
(f*) __permit_m=f;; # files only
|
|
(d*) __permit_m=d;; # directories only
|
|
|
|
(*)
|
|
printf >&2 'permit: unknown flag: -%.1s\n' "$__permit_f"
|
|
return 64;;
|
|
esac
|
|
done;;
|
|
(*) set -- "$@" "$__permit_f";;
|
|
esac
|
|
done
|
|
|
|
if [ $# = 0 ]; then
|
|
printf >&2 'usage: permit %s\n' "$__permit_h"
|
|
return 64;
|
|
fi
|
|
|
|
__permit_x=
|
|
for __permit_f; do
|
|
[ -n "$__permit_x" ] || { __permit_x=0; set --; }
|
|
if [ -x "$__permit_f" ]; then
|
|
: # pass
|
|
elif ! [ -e "$__permit_f" ]; then
|
|
set -- "$@" "$__permit_f"
|
|
elif [ "$__permit_a" = 1 ] && ! [ -d "$__permit_f" ]; then
|
|
__permit_4="$(__permit_hex "$__permit_f")" || __permit=$?
|
|
case "$__permit_4" in (7f454c46) false;; (2321*) false;; (4d5a*) false;;
|
|
esac || set -- "$@" "$__permit_f" # runs when a case matches
|
|
elif [ "-$__permit_m" "$__permit_f" ]; then
|
|
set -- "$@" "$__permit_f"
|
|
fi
|
|
done
|
|
|
|
[ "$__permit_v" = 0 ] || [ "$#" = 0 ] || printf >&2 'notice: +x %s\n' "$@"
|
|
[ "$__permit_n" = 1 ] || [ "$#" = 0 ] || chmod +x -- "$@" || __permit_x=$?
|
|
return "$__permit_x"
|
|
}
|
|
|
|
[ -n "${preload+-}" ] || permit "$@"
|