diff --git a/image/templates/files/bash_completion b/image/templates/files/bash_completion new file mode 100644 index 0000000..7ac603b --- /dev/null +++ b/image/templates/files/bash_completion @@ -0,0 +1,258 @@ +# This file is derived from completion fragments at +# https://github.com/OpenIndiana/openindiana-completions +# +# Portions Copyright 2006 Yann Rouillard +# Portions Copyright (c) 2013, Jonathan Perkin +# Portions copyright 2013, Nexenta Systems, Inc. +# Portions Copyright (c) 2018, Michal Nowak +# Portions Copyright 2024 Oxide Computer Company + +_zlogin() +{ + local cur prev line + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + line="${COMP_LINE}" + + # zlogin [-dCEQ] [-e c] [-l username] zonename + # zlogin [-nEQS] [-e c] [-l username] zonename utility [argument]... + local opts="-E -Q -e -l" + local opts_interactive="-d -C" + local opts_util="-n -S" + + if [[ "${cur}" == -* ]] + then + case "${line}" in + *\ -n\ *|*\ -S\ *) + COMPREPLY=( $(compgen -W "${opts} ${opts_util}" -- "${cur}") ) + ;; + *\ -d\ *|*\ -C\ *) + COMPREPLY=( $(compgen -W "${opts} ${opts_interactive}" -- "${cur}") ) + ;; + *) + COMPREPLY=( $(compgen -W "${opts} ${opts_util} ${opts_interactive}" -- "${cur}") ) + ;; + esac + else + # Provide running zone names + local zones=$(zoneadm list -n) + COMPREPLY=( $(compgen -W "${zones}" -- ${cur}) ) + fi +} + +_dash_z_zone() +{ + local cur prev + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${prev} =~ "-z" ]]; then + local zones="$(zoneadm list -n $*)" + COMPREPLY=( $(compgen -W "${zones}" -- ${cur}) ) + fi +} + +_dash_z_zone_running() { _dash_z_zone; } +_dash_z_zone_configured() { _dash_z_zone -c; } + +_smf_complete_fmri() +{ + local cur="$1" prefix="$2" + local cur_prefix fmri fmri_list="" + local exact_mode pattern + + if [[ "$cur" == $prefix* ]]; then + [[ "$cur" == $prefix ]] && cur+="/" + pattern="$cur*" + exact_mode=1 + else + pattern="$prefix*/$cur*" + fi + + cur_prefix="${cur%"${cur##*/}"}" + + for fmri in $(svcs -H -o FMRI "$pattern" 2>/dev/null); do + local fmri_part_list fmri_part + if [[ -z "$exact_mode" ]]; then + fmri=${fmri#$prefix/} + + # We generate all possibles abbreviations for the FMRI + # no need to have a generic loop as we will have a finite + # number of components. + local OIFS="$IFS"; IFS="/"; set -- $fmri; IFS="$OIFS" + case $# in + 1) fmri_part_list=" $1";; + 2) fmri_part_list=" $2 $1/$2";; + 3) fmri_part_list=" $3 $2/$3 $1/$2/$3";; + 4) fmri_part_list=" $4 $3/$4 $2/$3/$4 $1/$2/$3/$4";; + esac + else + fmri_part_list="$fmri" + fi + + # Here we make sure the completions begin with the pattern and + # we cut them at the first slash. + for fmri_part in $fmri_part_list; do + [[ "$fmri_part" == $cur* ]] || continue + local first_part=${fmri_part#$cur_prefix} + first_part=$cur_prefix${first_part%%/*} + [[ "$first_part" != "$fmri_part" ]] && first_part+="/" + fmri_list+=" $first_part" + done + done + + COMPREPLY=( $fmri_list ) + + # Here we want to detect if there is only one completion proposed and that + # it ends with a slash. That means the user will still have to complete + # after, so we save him one tab keystroke by immediately proposing the + # next completion alternatives. + local i=${#COMPREPLY[*]} + if [[ $i -gt 0 ]] && [[ "${COMPREPLY[$((--i))]}" == */ ]]; then + # We have to iterate throught the list as we may have duplicates. + while [[ $i -ne 0 ]]; do + [[ "${COMPREPLY[$i]}" != "${COMPREPLY[$((i - 1))]}" ]] && break + ((i--)) + done + if [[ $i -eq 0 ]]; then + _smf_complete_fmri "${COMPREPLY[0]}" "$prefix" + return + fi + fi + + # Work-around bash_completion issue where bash interprets a colon + # as a separator, borrowed from maven completion code which borrowed + # it from darcs completion code :). + local colonprefixes=${cur%"${cur##*:}"} + local i=${#COMPREPLY[*]} + while [ $((--i)) -ge 0 ]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$colonprefixes"} + done +} + +_svcadm() +{ + local cur prev words cword line + line="${COMP_LINE}" + _init_completion -n : || return + + local states="uninitialized offline online degraded maintenance disabled legacy-run" + local command_list="enable disable restart refresh clear mark milestone" + local command i + + for (( i=1; i < $cword; i++ )); do + if [[ ${words[i]} == @(enable|disable|restart|refresh|clear|mark|milestone) ]]; then + command=${words[i]} + fi + done + + if [[ -z "$command" ]]; then + # svcadm [-S state]... + if [[ ${prev} == -S ]]; then + COMPREPLY=( $(compgen -W "${states}" -- ${cur}) ) + elif [[ ${cur} == -* ]]; then + if [[ "$(zonename)" == "global" ]]; then + zones="-Z -z" + fi + COMPREPLY=( $(compgen -W "-S -v ${zones}" -- ${cur}) ) + else + # svcadm [-v] milestone [-d] milestone_FMRI + if [[ ${line} =~ -S ]]; then + command_list="$(echo ${command_list} | sed -e 's/milestone//')" + fi + COMPREPLY=( $(compgen -W "${command_list}" -- ${cur}) ) + fi + else + if [[ ${cur} == -* ]]; then + case "$command" in + enable) + # enable [-rst] + COMPREPLY=( $(compgen -W "-r -s -t" -- ${cur}) );; + disable) + # disable [-st] + COMPREPLY=( $(compgen -W "-s -t" -- ${cur}) );; + mark) + # mark [-It] + COMPREPLY=( $(compgen -W "-I -t" -- ${cur}) );; + milestone) + # milestone [-d] + COMPREPLY=( $(compgen -W "-d" -- ${cur}) );; + esac + else + if [[ "$command" == "mark" ]] && [[ "$prev" != @(degraded|maintenance) ]]; then + COMPREPLY=( $(compgen -W "degraded maintenance" -- ${cur}) ) + elif [[ "$command" == "milestone" ]]; then + _smf_complete_fmri "${cur}" "svc:/milestone" + else + _smf_complete_fmri "${cur}" "svc:" + fi + fi + fi + + _dash_z_zone_running +} + +_svcs() +{ + local cur prev + local svcs_cols="ctid desc fmri inst nsta nstate scope svc sta state stime" + + cur=${COMP_WORDS[COMP_CWORD]} + prev="${COMP_WORDS[COMP_CWORD-1]}" + + case "$prev" in + -o|-s|-S) + # -o col[,col]... -s col -S col + COMPREPLY=($(compgen -W "$svcs_cols" -- "${cur##*,}")) + local existing_opts=$(expr "$cur" : '\(.*,\)') + if [[ -n "$existing_opts" ]]; then + COMPREPLY=( "${COMPREPLY[@]/#/${existing_opts}}" ) + fi + if [[ ${prev} == -o ]]; then + compopt -o nospace + fi + return + ;; + esac + + if [[ $cur == -* ]]; then + # zone options are usable only in global zone + if [[ "$(zonename)" == "global" ]]; then + zones="-Z -z" + fi + COMPREPLY=( $(compgen -W "-? -a -H -p -o -s -S -d -D -R -l -L -v -x $zones" -- "${cur}") ) + else + _smf_complete_fmri "${cur}" "svc:" + fi + + _dash_z_zone_running +} + +complete -F _svcadm svcadm +complete -F _svcs svcs +complete -F _zlogin zlogin + +# Many illumos utilities are zone-aware through the -z option +# +complete -F _dash_z_zone_running allocate +complete -F _dash_z_zone_running deallocate +complete -F _dash_z_zone_running ipfs +complete -F _dash_z_zone_running ipfstat +complete -F _dash_z_zone_running ipmon +complete -F _dash_z_zone_running ipnat +complete -F _dash_z_zone_running ippool +complete -F _dash_z_zone_running pgrep +complete -F _dash_z_zone_running pkill +complete -F _dash_z_zone_running ps +complete -F _dash_z_zone_running psrset +complete -F _dash_z_zone_running ptree +complete -F _dash_z_zone_running svccfg +complete -F _dash_z_zone_running svcprop +complete -F _dash_z_zone_running wall + +complete -F _dash_z_zone_configured auditreduce +complete -F _dash_z_zone_configured zoneadm +complete -F _dash_z_zone_configured zonecfg + +# ex: filetype=sh +# vim: tabstop=2 shiftwidth=2 expandtab diff --git a/image/templates/files/bashrc b/image/templates/files/bashrc index 169f632..1a12ccf 100644 --- a/image/templates/files/bashrc +++ b/image/templates/files/bashrc @@ -45,6 +45,7 @@ pathdirs=( '/opt/ooce/bin' '/opt/oxide/opte/bin' '/opt/oxide/mg-ddm' + '/opt/oxide/oxlog' '/usr/sbin' '/usr/bin' '/bin' @@ -52,6 +53,9 @@ pathdirs=( ) export PATH=$(IFS=':'; printf '%s' "${pathdirs[*]}") +. /usr/share/bash-completion/bash_completion +. /usr/share/bash-completion/oxide + # # Bracketed paste in bash is a deeply questionable facility, and on a serial # console where one may reset the system at any time it leaves the terminal in diff --git a/image/templates/gimlet/ramdisk-02-trim.json b/image/templates/gimlet/ramdisk-02-trim.json index 434d330..90d4428 100644 --- a/image/templates/gimlet/ramdisk-02-trim.json +++ b/image/templates/gimlet/ramdisk-02-trim.json @@ -13,7 +13,9 @@ { "t": "remove_files", "dir": "/usr/demo" }, { "t": "remove_files", "dir": "/usr/lib/help" }, { "t": "remove_files", "dir": "/usr/share/doc" }, - { "t": "remove_files", "dir": "/usr/share/bash-completion" }, + { "t": "remove_files", + "dir": "/usr/share/bash-completion/completions" }, + { "t": "remove_files", "dir": "/usr/share/bash-completion/helpers" }, { "t": "remove_files", "dir": "/usr/perl5/5.36/man", "without": "recovery" }, @@ -106,6 +108,10 @@ "file": "/etc/motd", "src": "motd", "owner": "root", "group": "sys", "mode": "0644" }, + { "t": "ensure_file", + "file": "/usr/share/bash-completion/oxide", + "src": "bash_completion", + "owner": "root", "group": "root", "mode": "0644" }, { "t": "ensure_file", "file": "/etc/system.d/zfs:dbuf",