Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: completion of SELinux contexts



There are quite a number of commands that have an option that takes an
SELinux context as it's argument. Typically we've not handled this in
completion functions. However it isn't too hard to do a reasonable job
of completing them (apart from the level component which I don't really
understand). The following adds helper functions for contexts, users,
roles and types and a completion function for chcon (which comes from
util-linux). And modifies completions for cp, find, install, mkdir,
mknod and sudo to use the new helpers.

Oliver

diff --git a/Completion/Linux/Command/_chcon b/Completion/Linux/Command/_chcon
new file mode 100644
index 000000000..2d523f287
--- /dev/null
+++ b/Completion/Linux/Command/_chcon
@@ -0,0 +1,24 @@
+#compdef chcon
+
+local ign
+
+(( $#words > 2 )) && ign='!'
+_arguments -C -s -S \
+  '(-h --no-dereference)--dereference[dereference symlinks]' \
+  '(-h --no-dereference --dereference)'{-h,--no-dereference}'[operate on symlinks themselves]' \
+  '(1 -u --user -r --role  -l --range -t --type)--reference=[copy security context of specified file]:file:_files' \
+  '(1 --reference -u --user)'{-u+,--user=}'[set user in the target security context]: :_selinux_users' \
+  '(1 --reference -r --role)'{-r+,--role=}'[set role in the target security context]: :_selinux_roles' \
+  '(1 --reference -t --type)'{-t+,--type=}'[set type in the target security context]: :_selinux_types' \
+  '(1 --reference -l --range)'{-l+,--range=}'[set range in the target security context]:selinux range' \
+  '(--recursive -R)'{--recursive,-R}'[recurse subdirectories]' \
+  '(-v --verbose)'{-v,--verbose}'[output a diagnostic for every file processed]' \
+  '(-H -L -P)-H[follow symlinks on the command line]' \
+  '(-H -L -P)-L[follow all symlinks]' \
+  "(-H -L -P)-P[don't follow symlinks (default)]" \
+  '!(--preserve-root)--no-preserve-root' \
+  "--preserve-root[fail to operate recursively on '/']" \
+  '(--reference -u --user -r --role  -l --range -t --type)1:security context:_selinux_contexts' \
+  "${ign}--help[display help information]" \
+  "${ign}--version[display version information]" \
+  '*:file:_files'
diff --git a/Completion/Linux/Type/_selinux_contexts b/Completion/Linux/Type/_selinux_contexts
new file mode 100644
index 000000000..4c2cf4288
--- /dev/null
+++ b/Completion/Linux/Type/_selinux_contexts
@@ -0,0 +1,14 @@
+#autoload
+
+local -a parts suf
+
+parts=( users roles types )
+while compset -P 1 '*:' && (( $+parts[1] )) ; do
+  shift parts
+done
+if (( $+parts[1] )); then
+  compset -S ':*' || suf=( -S : )
+  _selinux_$parts[1] $suf
+else
+  _message -e selinux-ranges 'selinux range'
+fi
diff --git a/Completion/Linux/Type/_selinux_roles b/Completion/Linux/Type/_selinux_roles
new file mode 100644
index 000000000..92b4c36cb
--- /dev/null
+++ b/Completion/Linux/Type/_selinux_roles
@@ -0,0 +1,7 @@
+#autoload
+
+local -a seroles expl
+
+seroles=( ${(f)"$(_call_program selinux-roles seinfo --flat -r)"} )
+_description selinux-roles expl "selinux role"
+compadd "$@" "$expl[@]" -a seroles
diff --git a/Completion/Linux/Type/_selinux_types b/Completion/Linux/Type/_selinux_types
new file mode 100644
index 000000000..ef31f45d2
--- /dev/null
+++ b/Completion/Linux/Type/_selinux_types
@@ -0,0 +1,7 @@
+#autoload
+
+local -a setypes expl
+
+setypes=( ${(f)"$(_call_program selinux-types seinfo --flat -t)"} )
+_description selinux-types expl "selinux type"
+compadd "$@" "$expl[@]" -a setypes
diff --git a/Completion/Linux/Type/_selinux_users b/Completion/Linux/Type/_selinux_users
new file mode 100644
index 000000000..f046c92cf
--- /dev/null
+++ b/Completion/Linux/Type/_selinux_users
@@ -0,0 +1,8 @@
+#autoload
+
+local -a seusers expl
+
+seusers=( ${(f)"$(_call_program selinux-users seinfo --flat -u)"} )
+(( $#seusers )) || seusers=( guest_u root staff_u sysadm_u system_u unconfined_u user_u )
+_description selinux-users expl "selinux user"
+compadd "$@" "$expl[@]" -a seusers
diff --git a/Completion/Unix/Command/_cp b/Completion/Unix/Command/_cp
index ae448213a..f7411055b 100644
--- a/Completion/Unix/Command/_cp
+++ b/Completion/Unix/Command/_cp
@@ -32,7 +32,7 @@ if _pick_variant gnu=GNU unix --version; then
     '(-v --verbose)'{-v,--verbose}'[explain what is being done]' \
     '(-x --one-file-system)'{-x,--one-file-system}'[stay on this file system]' \
     '(--context)-Z[set destination SELinux security context]' \
-    '(-Z)--context=-[set destination SELinux security context]::context' \
+    '(-Z)--context=-[set destination SELinux security context]:: :_selinux_contexts' \
     '(- *)--help' '(- *)--version' \
     '*:file or directory:_files'
 else
diff --git a/Completion/Unix/Command/_find b/Completion/Unix/Command/_find
index 3b9150b17..916fcf2e6 100644
--- a/Completion/Unix/Command/_find
+++ b/Completion/Unix/Command/_find
@@ -98,7 +98,7 @@ case $variant in
     args+=(
       '(- *)-help' '(-)--help'
       '(- *)-version' '(-)--version'
-      '-D[print diagnostics]:debug option:(help tree search stat rates opt exec)'
+      '-D[print diagnostics]:debug option:(exec opt rates search stat time tree all help)'
       '-O+[enable query optimisation]:level:(1 2 3)'
       '*-daystart'
       '-regextype:regexp syntax:(help findutils-default awk egrep ed emacs gnu-awk grep posix-awk posix-basic posix-egrep posix-extended posix-minimal-basic sed)'
@@ -116,7 +116,7 @@ case $variant in
       '*-fprintf:output file:_files:output format'
       '*-printf:output format'
     )
-    [[ $OSTYPE = linux-gnu ]] && args+=( '*-context:SELinux context' )
+    [[ $OSTYPE = linux-gnu ]] && args+=( '*-context:SELinux context (glob pattern):_selinux_contexts' )
   ;;
 esac
 
diff --git a/Completion/Unix/Command/_install b/Completion/Unix/Command/_install
index 60b0f6153..5ad84645e 100644
--- a/Completion/Unix/Command/_install
+++ b/Completion/Unix/Command/_install
@@ -25,7 +25,7 @@ if _pick_variant gnu='Free Soft' unix --version; then
   args+=(
     $common_args
     '(-b --backup)--backup=[create backup; optionally specify method]:: :->controls'
-    "${lx}--context=[like -Z, or specify SELinux security context to set]::SELinux security context"
+    "${lx}--context=-[like -Z, or specify SELinux security context to set]::SELinux security context:_selinux_contexts"
     '-D[create all leading destination path components]'
     '(: -)--help[display help information]'
     "${lx}--preserve-context[preserve SELinux security context]"
diff --git a/Completion/Unix/Command/_mkdir b/Completion/Unix/Command/_mkdir
index 0ae6be14b..4cd6bda32 100644
--- a/Completion/Unix/Command/_mkdir
+++ b/Completion/Unix/Command/_mkdir
@@ -22,7 +22,8 @@ case $variant in
     aopts=()
     if [[ $OSTYPE == linux* ]]; then
       args+=(
-        '(-Z --context)'{-Z,--context=}'[set SELinux context]:SELinux context'
+        '(--context)-Z[set SELinux context]'
+        '(-Z)--context=-[set SELinux context]::SELinux context:_selinux_contexts'
       )
     fi
     args+=(
diff --git a/Completion/Unix/Command/_mkfifo b/Completion/Unix/Command/_mkfifo
index 4f1d8c87e..a055e4a1c 100644
--- a/Completion/Unix/Command/_mkfifo
+++ b/Completion/Unix/Command/_mkfifo
@@ -10,7 +10,7 @@ if _pick_variant gnu='Free Soft' unix --version; then
   )
   [[ $OSTYPE == linux* ]] && args+=(
     '(--context)-Z[set SELinux security context to default]'
-    '(-Z)--context=-[like -Z, or specify SELinux security context]:SELinux security context'
+    '(-Z)--context=-[like -Z, or specify SELinux security context]::SELinux security context:_selinux_contexts'
   )
 else
   aopts=( -A '-*' )
diff --git a/Completion/Unix/Command/_mknod b/Completion/Unix/Command/_mknod
index 902f49b9f..8f07328db 100644
--- a/Completion/Unix/Command/_mknod
+++ b/Completion/Unix/Command/_mknod
@@ -22,7 +22,7 @@ if _pick_variant gnu='Free Soft' $OSTYPE --version; then
   )
   [[ $OSTYPE == linux* ]] && args+=(
     '(--context)-Z[set SELinux security context to default]'
-    '(-Z)--context=-[like -Z, or specify SELinux security context]:SELinux security context'
+    '(-Z)--context=-[like -Z, or specify SELinux security context]::SELinux security context:_selinux_contexts'
   )
 else
   aopts=( -A '-*' )
diff --git a/Completion/Unix/Command/_sudo b/Completion/Unix/Command/_sudo
index 10fa2e82e..41e32cbae 100644
--- a/Completion/Unix/Command/_sudo
+++ b/Completion/Unix/Command/_sudo
@@ -23,9 +23,9 @@ args=(
   \*{-l,--list}"[list user's privileges or check a specific command]"
   '(-n --non-interactive)'{-n,--non-interactive}'[non-interactive mode, no prompts are used]'
   '(-p --prompt)'{-p+,--prompt=}'[use the specified password prompt]:prompt'
-  '(-r --role)'{-r+,--role=}'[create SELinux security context with specified role]:role'
+  '(-r --role)'{-r+,--role=}'[create SELinux security context with specified role]: :_selinux_roles'
   '(-S --stdin)'{-S,--stdin}'[read password from standard input]'
-  '(-t --type)'{-t+,--type=}'[create SELinux security context with specified type]:type'
+  '(-t --type)'{-t+,--type=}'[create SELinux security context with specified type]: :_selinux_types'
   '(-T --command-timeout)'{-T+,--command-timeout=}'[terminate command after specified time limit]:timeout'
   '(-U --other-user)'{-U+,--other-user=}'[in list mode, display privileges for user]:user:_users'
   '(-u --user)'{-u+,--user=}'[run command (or edit file) as specified user]:user:_users'



Messages sorted by: Reverse Date, Date, Thread, Author