1#autoload
2
3_svcs_fmri() {
4	local type="$argv[$#]"
5	local fmri_abbrevs m i
6	typeset -a -g _smf_fmris
7
8	local update_policy
9	zstyle -s ":completion:${curcontext}:" cache-policy update_policy
10	if [[ -z "$update_policy" ]]; then
11		zstyle ":completion:${curcontext}:" cache-policy _smf_caching_policy
12	fi
13	# The cache really must be per-host
14	local cache_id=smf_fmri:$HOST
15
16	# TODO: Do something useful with the expand and/or ambiguous styles.
17	case $type in
18	(-i|-c)
19		# We probably also need an option to eliminate ambiguous
20		# results for use in places where that's not allowed.
21
22		# Grab all FMRIs that have a word beginning with $PREFIX,
23		# making sure not to return the portion of the FMRI before
24		# $PREFIX.  Use the cache if it exists and the user wants to.
25		if ( [[ $#_smf_fmris -eq 0 ]] || _cache_invalid $cache_id ) \
26			&& ! _retrieve_cache $cache_id; then
27			_smf_fmris=( ${(f)"$(svcs -a -H -o fmri)"} )
28			_store_cache $cache_id _smf_fmris
29		fi
30		# Each element of the array is removed which doesn't match
31		# (^|.*/)$PREFIX.*
32		fmri_abbrevs=( ${(M)_smf_fmris:#((#s)|*[/:])$PREFIX*} )
33
34		# Go through the remaining elements and remove the characters
35		# in front of $PREFIX.
36		for ((i = 1; i <= $#fmri_abbrevs; i++ )); do
37			# Either one of these will work, but they're too
38			# greedy, preventing multiple matches below.
39			fmri_abbrevs[i]=${${fmri_abbrevs[i]}/((#s)|*[\/:])(#b)($PREFIX*)/$match[1]}
40			#fmri_abbrevs[i]=${${(M)${fmri_abbrevs[i]}:#(#b)((#s)|*/)$PREFIX*}#$match[1]}
41		done
42
43		# Remove the "default" instance identifier if it's the only
44		# instance for a given service (not for svccfg).
45		if [[ $type == "-i" ]]; then
46			local -a svcs insts nabbrevs
47			local s
48			svcs=( ${(u)fmri_abbrevs%:*} )
49			for s in $svcs; do
50				insts=( ${(@M)fmri_abbrevs:#$s:*} )
51				if [[ $#insts -eq 1 && $insts[1] == *":default" ]]; then
52					nabbrevs=($nabbrevs ${insts//:default})
53				elif [[ $#insts -eq 0 ]]; then
54					# Turns out we're completing the
55					# instance name.
56					nabbrevs=($nabbrevs $s)
57				else
58					nabbrevs=($nabbrevs $insts)
59				fi
60			done
61			fmri_abbrevs=( $nabbrevs )
62		fi
63
64		# After playing with _multi_parts, I'm not sure it's actually
65		# that useful.
66		# _wanted fmri expl "full or unambiguously abbreviated FMRIs" \
67		# 	_multi_parts -i / fmri_abbrevs
68
69		_wanted fmri expl "full or unambiguously abbreviated FMRIs" \
70			compadd $fmri_abbrevs
71		;;
72
73	(-m)
74		_wanted fmri expl "milestone FMRIs" \
75			compadd $(svcs -H -o fmri svc:/milestone/\*) all
76		;;
77
78	(-r)
79		# TODO: need some way to pick out only restarters
80		_wanted fmri expl "restarter FMRIs" \
81			compadd master reset svc:/network/inetd:default
82		;;
83
84	(*)
85		_message "unknown argument to _svcs_fmri: $type"
86		;;
87	esac
88}
89
90_smf_caching_policy() {
91	# /etc/svc/repository.db is not a public interface, so this is kinda
92	# grody.
93	[[ ! -f "$1" || /etc/svc/repository.db -nt "$1" ]]
94}
95
96_svcs_fmri "$@"
97