netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / utilities / ovs-vsctl-bashcomp.bash
1 SAVE_IFS=$IFS
2 IFS="
3 "
4 _OVSDB_SERVER_LOCATION=""
5
6 # Run ovs-vsctl and make sure that ovs-vsctl is always called with
7 # the correct --db argument.
8 _ovs_vsctl () {
9     local _db
10
11     if [ -n "$_OVSDB_SERVER_LOCATION" ]; then
12         _db="--db=$_OVSDB_SERVER_LOCATION"
13     fi
14     ovs-vsctl ${_db} "$@"
15 }
16
17 # ovs-vsctl --commands outputs in this format:
18 #
19 # main = <localopts>,<name>,<options>
20 # localopts = ([<localopt>] )*
21 # localopt = --[^]]*
22 # name = [^,]*
23 # arguments = ((!argument|?argument|*argument|+argument) )*
24 # argument = ([^ ]*|argument\|argument)
25 #
26 # The [] characters in local options are just delimiters.  The
27 # argument prefixes mean:
28 #   !argument :: The argument is required
29 #   ?argument :: The argument is optional
30 #   *argument :: The argument may appear any number (0 or more) times
31 #   +argument :: The argument may appear one or more times
32 # A bar (|) character in an argument means thing before bar OR thing
33 # after bar; for example, del-port can take a port or an interface.
34
35 _OVS_VSCTL_COMMANDS="$(_ovs_vsctl --commands)"
36
37 # This doesn't complete on short arguments, so it filters them out.
38 _OVS_VSCTL_OPTIONS="$(_ovs_vsctl --options | awk '/^--/ { print $0 }' \
39                       | sed -e 's/\(.*\)=ARG/\1=/')"
40 IFS=$SAVE_IFS
41
42 declare -A _OVS_VSCTL_PARSED_ARGS
43 declare -A _OVS_VSCTL_NEW_RECORDS
44
45 # This is a convenience function to make sure that user input is
46 # looked at as a fixed string when being compared to something.  $1 is
47 # the input; this behaves like 'grep "^$1"' but deals with regex
48 # metacharacters in $1.
49 _ovs_vsctl_check_startswith_string () {
50     awk 'index($0, thearg)==1' thearg="$1"
51 }
52
53 # $1 = word to complete on.
54 # Complete on global options.
55 _ovs_vsctl_bashcomp_globalopt () {
56     local options result
57
58     options=""
59     result=$(printf "%s\n" "${_OVS_VSCTL_OPTIONS}" \
60              | _ovs_vsctl_check_startswith_string "${1%=*}")
61     if [[ $result =~ "=" ]]; then
62         options="NOSPACE"
63     fi
64     printf -- "${options}\nEO\n${result}"
65 }
66
67 # $1 = word to complete on.
68 # Complete on local options.
69 _ovs_vsctl_bashcomp_localopt () {
70     local options result possible_opts
71
72     possible_opts=$(printf "%s\n" "${_OVS_VSCTL_COMMANDS}" | cut -f1 -d',')
73     # This finds all options that could go together with the
74     # already-seen ones
75     for prefix_arg in $1; do
76         possible_opts=$(printf "%s\n" "$possible_opts" \
77                         | grep -- "\[${prefix_arg%%=*}=\?\]")
78     done
79     result=$(printf "%s\n" "${possible_opts}" \
80              | tr ' ' '\n' | tr -s '\n' | sort | uniq)
81     # This removes the already-seen options from the list so that
82     # users aren't completed for the same option twice.
83     for prefix_arg in $1; do
84         result=$(printf "%s\n" "${result}" \
85                  | grep -v -- "\[${prefix_arg%%=*}=\?\]")
86     done
87     result=$(printf "%s\n" "${result}" | sed -ne 's/\[\(.*\)\]/\1/p' \
88              | _ovs_vsctl_check_startswith_string "$2")
89     if [[ $result =~ "=" ]]; then
90         options="NOSPACE"
91     fi
92     printf -- "${options}\nEO\n${result}"
93 }
94
95 # $1 = given local options.
96 # $2 = word to complete on.
97 # Complete on command that could contain the given local options.
98 _ovs_vsctl_bashcomp_command () {
99     local result possible_cmds
100
101     possible_cmds=$(printf "%s\n" "${_OVS_VSCTL_COMMANDS}")
102     for prefix_arg in $1; do
103         possible_cmds=$(printf "%s\n" "$possible_cmds" \
104                         | grep -- "\[$prefix_arg=\?\]")
105     done
106     result=$(printf "%s\n" "${possible_cmds}" \
107              | cut -f2 -d',' \
108              | _ovs_vsctl_check_startswith_string "$2")
109     printf -- "${result}"
110 }
111
112 # $1 = completion result to check.
113 # Return 0 if the completion result is non-empty, otherwise return 1.
114 _ovs_vsctl_detect_nonzero_completions () {
115     local tmp newarg
116
117     newarg=${1#*EO}
118     readarray tmp <<< "$newarg"
119     if [ "${#tmp[@]}" -eq 1 ] && [ "${#newarg}" -eq 0 ]; then
120         return 1
121     fi
122     return 0
123 }
124
125 # $1 = argument format to expand.
126 # Expand '+ARGUMENT' in argument format to '!ARGUMENT *ARGUMENT'.
127 _ovs_vsctl_expand_command () {
128     result=$(printf "%s\n" "${_OVS_VSCTL_COMMANDS}" \
129              | grep -- ",$1," | cut -f3 -d',' | tr ' ' '\n' \
130              | awk '/\+.*/ { name=substr($0,2);
131                              print "!"name; print "*"name; next; }
132                     1')
133     printf -- "${result}\n!--"
134 }
135
136 # $1 = word to complete on.
137 # Complete on table.
138 _ovs_vsctl_complete_table () {
139     local result
140
141     result=$(ovsdb-client --no-heading list-tables $_OVSDB_SERVER_LOCATION Open_vSwitch \
142         | _ovs_vsctl_check_startswith_string "$1")
143     printf -- "EO\n%s\n" "${result}"
144 }
145
146 # $1 = word to complete on.
147 # Complete on record.  Provide both the name and uuid.
148 _ovs_vsctl_complete_record () {
149     local table uuids names new_record
150
151     table="${_OVS_VSCTL_PARSED_ARGS[TABLE]}"
152     new_record="${_OVS_VSCTL_NEW_RECORDS[${table^^}]}"
153     # Tables should always have an _uuid column
154     uuids=$(_ovs_vsctl --no-heading -f table -d bare --columns=_uuid \
155                       list $table | _ovs_vsctl_check_startswith_string "$1")
156     # Names don't always exist, silently ignore if the name column is
157     # unavailable.
158     names=$(_ovs_vsctl --no-heading -f table -d bare \
159                       --columns=name list $table \
160                       2>/dev/null \
161             | _ovs_vsctl_check_startswith_string "$1")
162     printf -- "EO\n%s\n%s\n%s\n" "${uuids}" "${names}" "${new_record}"
163 }
164
165 # $1 = word to complete on.
166 # Complete on bridge.
167 _ovs_vsctl_complete_bridge () {
168     local result
169
170     result=$(_ovs_vsctl list-br | _ovs_vsctl_check_startswith_string "$1")
171     printf -- "EO\n%s\n" "${result}"
172 }
173
174 # $1 = word to complete on.
175 # Complete on port.  If a bridge has already been specified,
176 # just complete for that bridge.
177 _ovs_vsctl_complete_port () {
178     local ports result
179
180     if [ -n "${_OVS_VSCTL_PARSED_ARGS[BRIDGE]}" ]; then
181         ports=$(_ovs_vsctl list-ports "${_OVS_VSCTL_PARSED_ARGS[BRIDGE]}")
182     else
183         local all_ports
184         all_ports=$(_ovs_vsctl --format=table \
185                               --no-headings \
186                               --columns=name \
187                               list Port)
188         ports=$(printf "$all_ports" | tr -d '" ' | sort -u)
189     fi
190     result=$(_ovs_vsctl_check_startswith_string "$1" <<< "$ports")
191     printf -- "EO\n%s\n" "${result}"
192 }
193
194 # $1:  Atom to complete (as usual)
195 # $2:  Table to complete the key in
196 # $3:  Column to find keys in
197 # $4:  Prefix for each completion
198 # Complete on key based on given table and column info.
199 _ovs_vsctl_complete_key_given_table_column () {
200     local keys
201
202     keys=$(_ovs_vsctl --no-heading --columns="$3" list \
203                      "$2" \
204            | tr -d '{\"}' | tr -s ', ' '\n' | cut -d'=' -f1 \
205            | xargs printf "$4%s\n" | _ovs_vsctl_check_startswith_string "$4$1")
206     result="${keys}"
207     printf -- "%s\n" "${result}"
208 }
209
210 # $1 = word to complete on.
211 # Complete on key.
212 __complete_key () {
213     # KEY is used in both br-set-external-id/br-get-external id (in
214     # which case it is implicitly a key in the external-id column) and
215     # in remove, where it is a table key.  This checks to see if table
216     # is set (the remove scenario), and then decides what to do.
217     local result
218
219     if [ -n "${_OVS_VSCTL_PARSED_ARGS[TABLE]}" ]; then
220         local column=$(tr -d '\n' <<< ${_OVS_VSCTL_PARSED_ARGS["COLUMN"]})
221         result=$(_ovs_vsctl_complete_key_given_table_column \
222                      "$1" \
223                      ${_OVS_VSCTL_PARSED_ARGS["TABLE"]} \
224                      $column \
225                      "")
226     else
227         result=$(_ovs_vsctl br-get-external-id \
228                            ${_OVS_VSCTL_PARSED_ARGS["BRIDGE"]} \
229                  | cut -d'=' -f1 | _ovs_vsctl_check_startswith_string "$1")
230     fi
231     printf -- "%s" "${result}"
232 }
233
234 # $1 = word to complete on.
235 # Complete on key.
236 _ovs_vsctl_complete_key () {
237     # KEY is used in both br-set-external-id/br-get-external id (in
238     # which case it is implicitly a key in the external-id column) and
239     # in remove, where it is a table key.  This checks to see if table
240     # is set (the remove scenario), and then decides what to do.
241     local result
242
243     result="$(__complete_key $1)"
244     # If result is empty, just use user input as result.
245     if [ -z "$result" ]; then
246         result=$1
247     fi
248     printf -- "EO\n%s\n" "${result}"
249 }
250
251 # $1 = word to complete on.
252 # Complete on value.
253 _ovs_vsctl_complete_value () {
254     local result
255
256     # Just use user input as result.
257     result=$1
258
259     printf -- "EO\n%s\n" "${result}"
260 }
261
262 # $1 = word to complete on.
263 # Complete on key=value.
264 _ovs_vsctl_complete_key_value () {
265     local orig_completions new_completions
266
267     orig_completions=$(__complete_key "$1")
268     for completion in ${orig_completions#*EO}; do
269         new_completions="${new_completions} ${completion}="
270     done
271     # If 'new_completions' is empty, just use user input as result.
272     if [ -z "$new_completions" ]; then
273         new_completions=$1
274     fi
275     printf -- "NOSPACE\nEO\n%s" "${new_completions}"
276 }
277
278 # $1 = word to complete on.
279 # Complete on column.
280 _ovs_vsctl_complete_column () {
281     local columns result
282
283     columns=$(ovsdb-client --no-headings list-columns $_OVSDB_SERVER_LOCATION \
284         Open_vSwitch ${_OVS_VSCTL_PARSED_ARGS["TABLE"]})
285     result=$(printf "%s\n" "${columns}" \
286              | tr -d ':' | cut -d' ' -f1 \
287              | _ovs_vsctl_check_startswith_string "$1" | sort | uniq)
288     printf -- "EO\n%s\n" "${result}"
289 }
290
291 # Extract all system interfaces.
292 _ovs_vsctl_get_sys_intf () {
293     local result
294
295     case "$(uname -o)" in
296         *Linux*)
297             result=$(ip -o link 2>/dev/null | cut -d':' -f2 \
298                      | sed -e 's/^ \(.*\)/\1/')
299             ;;
300         *)
301             result=$(ifconfig -a -s 2>/dev/null | cut -f1 -d' ' | tail -n +2)
302             ;;
303     esac
304     printf "%s\n" "${result}"
305 }
306
307 # $1 = word to complete on.
308 # Complete on system interface.
309 _ovs_vsctl_complete_sysiface () {
310     local result
311
312     result=$(_ovs_vsctl_get_sys_intf | _ovs_vsctl_check_startswith_string "$1")
313     printf -- "EO\n%s\n" "${result}"
314 }
315
316 # $1 = word to complete on.
317 # Complete on interface.  If a bridge has already been specified,
318 # just complete for that bridge.
319 _ovs_vsctl_complete_iface () {
320     local result
321
322     if [ -n "${_OVS_VSCTL_PARSED_ARGS[BRIDGE]}" ]; then
323         result=$(_ovs_vsctl list-ifaces "${_OVS_VSCTL_PARSED_ARGS[BRIDGE]}")
324     else
325         for bridge in $(_ovs_vsctl list-br); do
326             local ifaces
327
328             ifaces=$(_ovs_vsctl list-ifaces "${bridge}")
329             result="${result} ${ifaces}"
330         done
331     fi
332     printf "EO\n%s\n" "${result}"
333 }
334
335 # $1 = word to complete on.
336 # Complete on COLUMN?:KEY=VALUE.
337 _ovs_vsctl_complete_column_optkey_value () {
338     local result column key value completion
339
340     column=$(printf "%s\n" "$1" | cut -d '=' -f1 | cut -d':' -f1)
341     key=$(printf "%s\n" "$1" | cut -d '=' -f1 | cut -s -d':' -f2)
342     # The tr -d '\n' <<< makes sure that there are no leading or
343     # trailing accidental newlines.
344     table=$(tr -d '\n' <<< ${_OVS_VSCTL_PARSED_ARGS["TABLE"]})
345     # This might also be called after add-port or add-bond; in those
346     # cases, the table should implicitly be assumed to be "Port".
347     # This is done by checking if a NEW- parameter has been
348     # encountered and, if it has, using that type without the NEW- as
349     # the table.
350     if [ -z "$table" ]; then
351         if [ -n ${_OVS_VSCTL_PARSED_ARGS["NEW-PORT"]} ] \
352            || [ -n ${_OVS_VSCTL_PARSED_ARGS["NEW-BOND-PORT"]} ]; then
353             table="Port"
354         fi
355     fi
356     if [ -z "$key" ]; then
357         local columns=$(ovsdb-client --no-headings list-columns \
358             $_OVSDB_SERVER_LOCATION Open_vSwitch $table)
359
360         result=$(printf "%s\n" "${columns}" \
361                  | awk '/key.*value/ { print $1":"; next }
362                                      { print $1; next }' \
363                  | _ovs_vsctl_check_startswith_string "$1" | sort | uniq)
364     fi
365     if [[ $1 =~ ":" ]]; then
366         result=$(_ovs_vsctl_complete_key_given_table_column \
367                      "$key" "$table" "$column" "$column:")
368     fi
369     # If result is empty, just use user input as result.
370     if [ -z "$result" ]; then
371         result=$1
372     fi
373     printf -- "NOSPACE\nEO\n%s\n" "${result}"
374 }
375
376 # $1 = word to complete on.
377 # Complete on filename.
378 _ovs_vsctl_complete_filename () {
379     local result
380
381     result=$(compgen -o filenames -A file "$1")
382     printf -- "EO\n%s\n" "${result}"
383 }
384
385 _ovs_vsctl_complete_bridge_fail_mode () {
386     printf -- "EO\nstandalone\nsecure"
387 }
388
389 # $1 = word to complete on.
390 # Complete on target.
391 _ovs_vsctl_complete_target () {
392     local result
393
394     if [[ "$1" =~ ^p?u ]]; then
395         local protocol pathname expansion_base result
396
397         protocol=$(cut -d':' -f1 <<< "$1")
398         pathname=$(cut -s -d':' -f2 <<< "$1")
399         expansion_base=$(compgen -W "unix punix" "$protocol")
400         expansion_base="$expansion_base:"
401         result=$(compgen -o filenames -A file \
402                          -P $expansion_base "${pathname}")
403         printf -- "NOSPACE\nEO\n%s\n" "${result}"
404     else
405         printf -- "NOSPACE\nEO\nssl:\ntcp:\nunix:\npssl:\nptcp:\npunix:"
406     fi
407 }
408
409 # Extract PS1 prompt.
410 _ovs_vsctl_get_PS1 () {
411     if [ "$test" = "true" ]; then
412         printf -- "> "
413         return;
414     fi
415
416     # Original inspiration from
417     # http://stackoverflow.com/questions/10060500/bash-how-to-evaluate-ps1-ps2,
418     # but changed quite a lot to make it more robust.
419
420     # Make sure the PS1 used doesn't include any of the special
421     # strings used to identify the prompt
422     myPS1="$(sed 's/Begin prompt/\\Begin prompt/; s/End prompt/\\End prompt/' <<< "$PS1")"
423     # Export the current environment in case the prompt uses any
424     vars="$(env | cut -d'=' -f1)"
425     for var in $vars; do export $var; done
426     funcs="$(declare -F | cut -d' ' -f3)"
427     for func in $funcs; do export -f $func; done
428     # Get the prompt
429     v="$(bash --norc --noprofile -i 2>&1 <<< $'PS1=\"'"$myPS1"$'\" \n# Begin prompt\n# End prompt')"
430     v="${v##*# Begin prompt}"
431     printf -- "$(tail -n +2 <<< "${v%# End prompt*}" | sed 's/\\Begin prompt/Begin prompt/; s/\\End prompt/End prompt/')"
432
433 }
434
435 # Request a new value from user.  Nothing to complete on.
436 _ovs_vsctl_complete_new () {
437     local two_word_type message result
438
439     if [ ! "$1" = "--" ]; then
440         two_word_type="${2/-/ }"
441         message="\nEnter a ${two_word_type,,}:\n$(_ovs_vsctl_get_PS1)$COMP_LINE"
442         if [ -n "$1" ]; then
443             result="$1"
444         fi
445         printf -- "NOCOMP\nBM%sEM\nEO\n%s\n" "${message}" "${result}"
446     fi
447 }
448
449 _ovs_vsctl_complete_dashdash () {
450     printf -- "EO\n%s\n" "--"
451 }
452
453
454 # These functions are given two arguments:
455 #
456 # $1 is the word being completed
457 #
458 # $2 is the type of completion --- only currently useful for the
459 # NEW-* functions.
460 #
461 # Note that the NEW-* functions actually are ``completed''; currently
462 # the completions are just used to save the fact that they have
463 # appeared for later use (i.e. implicit table calculation).
464 #
465 # The output is of the form <options>EO<completions>, where EO stands
466 # for end options.  Currently available options are:
467 #  - NOSPACE: Do not add a space at the end of each completion
468 #  - NOCOMP: Do not complete, but store the output of the completion
469 #    func in _OVS_VSCTL_PARSED_ARGS for later usage.
470 #  - BM<message>EM: Print the <message>
471 declare -A _OVS_VSCTL_ARG_COMPLETION_FUNCS=(
472     ["TABLE"]=_ovs_vsctl_complete_table
473     ["RECORD"]=_ovs_vsctl_complete_record
474     ["BRIDGE"]=_ovs_vsctl_complete_bridge
475     ["PARENT"]=_ovs_vsctl_complete_bridge
476     ["PORT"]=_ovs_vsctl_complete_port
477     ["KEY"]=_ovs_vsctl_complete_key
478     ["VALUE"]=_ovs_vsctl_complete_value
479     ["ARG"]=_ovs_vsctl_complete_value
480     ["IFACE"]=_ovs_vsctl_complete_iface
481     ["SYSIFACE"]=_ovs_vsctl_complete_sysiface
482     ["COLUMN"]=_ovs_vsctl_complete_column
483     ["COLUMN?:KEY"]=_ovs_vsctl_complete_column_optkey_value
484     ["COLUMN?:KEY=VALUE"]=_ovs_vsctl_complete_column_optkey_value
485     ["KEY=VALUE"]=_ovs_vsctl_complete_key_value
486     ["?KEY=VALUE"]=_ovs_vsctl_complete_key_value
487     ["PRIVATE-KEY"]=_ovs_vsctl_complete_filename
488     ["CERTIFICATE"]=_ovs_vsctl_complete_filename
489     ["CA-CERT"]=_ovs_vsctl_complete_filename
490     ["MODE"]=_ovs_vsctl_complete_bridge_fail_mode
491     ["TARGET"]=_ovs_vsctl_complete_target
492     ["NEW-BRIDGE"]=_ovs_vsctl_complete_new
493     ["NEW-PORT"]=_ovs_vsctl_complete_new
494     ["NEW-BOND-PORT"]=_ovs_vsctl_complete_new
495     ["NEW-VLAN"]=_ovs_vsctl_complete_new
496     ["--"]=_ovs_vsctl_complete_dashdash
497 )
498
499 # $1: Argument type, may include vertical bars to mean OR
500 # $2: Beginning of completion
501 #
502 # Note that this checks for existance in
503 # _OVS_VSCTL_ARG_COMPLETION_FUNCS; if the argument type ($1) is not
504 # there it will fail gracefully.
505 _ovs_vsctl_possible_completions_of_argument () {
506     local possible_types completions tmp
507
508     completions="EO"
509
510     possible_types=$(printf "%s\n" "$1" | tr '|' '\n')
511     for type in $possible_types; do
512         if [ ${_OVS_VSCTL_ARG_COMPLETION_FUNCS["${type^^}"]} ]; then
513             tmp=$(${_OVS_VSCTL_ARG_COMPLETION_FUNCS["${type^^}"]} \
514                       "$2" "${type^^}")
515             tmp_noEO="${tmp#*EO}"
516             tmp_EO="${tmp%%EO*}"
517             completions=$(printf "%s%s\n%s" "${tmp_EO}" \
518                                  "${completions}" "${tmp_noEO}")
519         fi
520     done
521     printf "%s\n" "${completions}"
522 }
523
524 # $1 = List of argument types
525 # $2 = current pointer into said list
526 # $3 = word to complete on
527 # Outputs list of possible completions
528 # The return value is the index in the cmd_args($1) list that should
529 # next be matched, if only one of them did, or 254 if there are no
530 # matches, so it doesn't know what comes next.
531 _ovs_vsctl_complete_argument() {
532     local cmd_args arg expansion index
533
534     new=$(printf "%s\n" "$1" | grep -- '.\+')
535     readarray -t cmd_args <<< "$new";
536     arg=${cmd_args[$2]}
537     case ${arg:0:1} in
538         !)
539             expansion=$(_ovs_vsctl_possible_completions_of_argument \
540                             "${arg:1}" $3)
541             index=$(($2+1))
542             ;;
543         \?|\*)
544             local tmp1 tmp2 arg2_index tmp2_noEO tmp2_EO
545             tmp1=$(_ovs_vsctl_possible_completions_of_argument "${arg:1}" $3)
546             tmp2=$(_ovs_vsctl_complete_argument "$1" "$(($2+1))" "$3")
547             arg2_index=$?
548             if _ovs_vsctl_detect_nonzero_completions "$tmp1" \
549                && _ovs_vsctl_detect_nonzero_completions "$tmp2"; then
550                 if [ "${arg:0:1}" = "*" ]; then
551                     index=$2;
552                 else
553                     index=$(($2+1));
554                 fi
555             fi
556             if _ovs_vsctl_detect_nonzero_completions "$tmp1" \
557                && (! _ovs_vsctl_detect_nonzero_completions "$tmp2"); then
558                 if [ "${arg:0:1}" = "*" ]; then
559                     index=$2;
560                 else
561                     index=$(($2+1));
562                 fi
563             fi
564             if (! _ovs_vsctl_detect_nonzero_completions "$tmp1") \
565                && _ovs_vsctl_detect_nonzero_completions "$tmp2"; then
566                 index=$arg2_index
567             fi
568             if (! _ovs_vsctl_detect_nonzero_completions "$tmp1") \
569                && (! _ovs_vsctl_detect_nonzero_completions "$tmp2"); then
570                 index=254
571             fi
572             # Don't allow secondary completions to inhibit primary
573             # completions:
574             if [[ $tmp2 =~ ^([^E]|E[^O])*NOCOMP ]]; then
575                 tmp2=""
576             fi
577             tmp2_noEO="${tmp2#*EO}"
578             tmp2_EO="${tmp2%%EO*}"
579             expansion=$(printf "%s%s\n%s" "${tmp2_EO}" \
580                                "${tmp1}" "${tmp2_noEO}")
581             ;;
582     esac
583     printf "%s\n" "$expansion"
584     return $index
585 }
586
587 _ovs_vsctl_detect_nospace () {
588     if [[ $1 =~ ^([^E]|E[^O])*NOSPACE ]]; then
589         _OVS_VSCTL_COMP_NOSPACE=true
590     fi
591 }
592
593 _ovs_vsctl_process_messages () {
594     local message
595
596     message="${1#*BM}"
597     message="${message%%EM*}"
598     if [ "$test" = "true" ]; then
599         printf -- "--- BEGIN MESSAGE"
600     fi
601     printf "${message}"
602     if [ "$test" = "true" ]; then
603         printf -- "--- END MESSAGE"
604     fi
605 }
606
607 # colon, equal sign will mess up the completion output, just
608 # removes the colon-word and equal-word prefix from COMPREPLY items.
609 #
610 # Implementation of this function refers to the __ltrim_colon_completions
611 # function defined in bash_completion module.
612 #
613 # $1:  Current argument
614 # $2:  $COMP_WORDBREAKS
615 # $3:  ${COMPREPLY[@]}
616 _ovs_vsctl_trim_compreply() {
617     local cur comp_wordbreaks
618     local compreply
619
620     cur=$1 && shift
621     comp_wordbreaks=$1 && shift
622     compreply=( $@ )
623
624     if [[ "$cur" == *:* && "$comp_wordbreaks" == *:* ]]; then
625         local colon_word=${cur%${cur##*:}}
626         local i=${#compreply[*]}
627         cur=${cur##*:}
628         while [ $((--i)) -ge 0 ]; do
629             compreply[$i]=${compreply[$i]#"$colon_word"}
630         done
631     fi
632
633     if [[ "$cur" == *=* && "$comp_wordbreaks" == *=* ]]; then
634         local equal_word=${cur%${cur##*=}}
635         local i=${#compreply[*]}
636         while [ $((--i)) -ge 0 ]; do
637             compreply[$i]=${compreply[$i]#"$equal_word"}
638         done
639     fi
640
641     printf "%s " "${compreply[@]}"
642 }
643
644 # The general strategy here is that the same functions that decide
645 # completions can also capture the necessary context for later
646 # completions.  This means that there is no distinction between the
647 # processing for words that are not the current word and words that
648 # are the current word.
649 #
650 # Parsing up until the command word happens starts with everything
651 # valid; as the syntax order of ovs-vsctl is fairly strict, when types
652 # of words that preclude other words from happending can turn them
653 # off; this is controlled by valid_globals, valid_opts, and
654 # valid_commands.  given_opts is used to narrow down which commands
655 # are valid based on the previously given options.
656 #
657 # After the command has been detected, the parsing becomes more
658 # complicated.  The cmd_pos variable is set to 0 when the command is
659 # detected; it is used as a pointer into an array of the argument
660 # types for that given command.  The argument types are stored in both
661 # cmd_args and raw_cmd as the main loop uses properties of arrays to
662 # detect certain conditions, but arrays cannot be passed to functions.
663 # To be able to deal with optional or repeatable arguments, the exit
664 # status of the function _ovs_vsctl_complete_argument represents where
665 # it has determined that the next argument will be.
666 _ovs_vsctl_bashcomp () {
667     local words cword valid_globals cmd_args raw_cmd cmd_pos valid_globals valid_opts
668     local test="false"
669
670     # Does not support BASH_VERSION < 4.0
671     if [ ${BASH_VERSINFO[0]} -lt 4 ]; then
672         return 0
673     fi
674
675     # Prepare the COMP_* variables based on input.
676     if [ "$1" = "test" ]; then
677         test="true"
678         export COMP_LINE="ovs-vsctl $2"
679         tmp="ovs-vsctl"$'\n'"$(tr ' ' '\n' <<< "${COMP_LINE}x")"
680         tmp="${tmp%x}"
681         readarray -t COMP_WORDS \
682                   <<< "$tmp"
683         export COMP_WORDS
684         export COMP_CWORD="$((${#COMP_WORDS[@]}-1))"
685     else
686         # If not in test mode, reassembles the COMP_WORDS and COMP_CWORD
687         # using just space as word break.
688         _get_comp_words_by_ref -n "\"'><=;|&(:" -w words -i cword
689         COMP_WORDS=( "${words[@]}" )
690         COMP_CWORD=${cword}
691     fi
692
693     # Extract the conf.db path.
694     db=$(sed -n 's/.*--db=\([^ ]*\).*/\1/p' <<< "$COMP_LINE")
695     if [ -n "$db" ]; then
696         _OVSDB_SERVER_LOCATION="$db"
697     fi
698
699     # If having trouble accessing the database, return.
700     if ! _ovs_vsctl get-manager 1>/dev/null 2>/dev/null; then
701         return 1;
702     fi
703
704     _OVS_VSCTL_PARSED_ARGS=()
705     _OVS_VSCTL_NEW_RECORDS=()
706     cmd_pos=-1
707     valid_globals=true
708     valid_opts=true
709     valid_commands=true
710     given_opts=""
711     index=1
712     for word in "${COMP_WORDS[@]:1:${COMP_CWORD}} "; do
713         _OVS_VSCTL_COMP_NOSPACE=false
714         local completion
715         completion=""
716         if [ $cmd_pos -gt -1 ]; then
717             local tmp tmp_noop arg possible_newindex
718             tmp=$(_ovs_vsctl_complete_argument "$raw_cmd" "$cmd_pos" "$word")
719             possible_newindex=$?
720             # Check for nospace.
721             _ovs_vsctl_detect_nospace $tmp
722             # Remove all options.
723             tmp_noop="${tmp#*EO}"
724
725             # Allow commands to specify that they should not be
726             # completed
727             if ! [[ $tmp =~ ^([^E]|E[^O])*NOCOMP ]]; then
728                 # Directly assignment, since 'completion' is guaranteed to
729                 # to be empty.
730                 completion="$tmp_noop"
731                 # If intermediate completion is empty, it means that the current
732                 # argument is invalid.  And we should not continue.
733                 if [ $index -lt $COMP_CWORD ] \
734                     && (! _ovs_vsctl_detect_nonzero_completions "$completion"); then
735                     _ovs_vsctl_process_messages "BM\nCannot complete \'${COMP_WORDS[$index]}\' at index ${index}:\n$(_ovs_vsctl_get_PS1)${COMP_LINE}EM\nEO\n"
736                     return 1
737                 fi
738             else
739                 # Only allow messages when there is no completion
740                 # printout and when on the current word.
741                 if [ $index -eq $COMP_CWORD ]; then
742                     _ovs_vsctl_process_messages "${tmp}"
743                 fi
744                 # Append the new record to _OVS_VSCTL_NEW_RECORDS.
745                 _OVS_VSCTL_NEW_RECORDS["${cmd_args[$cmd_pos]##*-}"]="${_OVS_VSCTL_NEW_RECORDS["${cmd_args[$cmd_pos]##*-}"]} $tmp_noop"
746             fi
747             if [[ $cmd_pos -lt ${#cmd_args} ]]; then
748                 _OVS_VSCTL_PARSED_ARGS["${cmd_args[$cmd_pos]:1}"]=$word
749             fi
750             if [ $possible_newindex -lt 254 ]; then
751                 cmd_pos=$possible_newindex
752             fi
753         fi
754
755         if [ $valid_globals == true ]; then
756             tmp=$(_ovs_vsctl_bashcomp_globalopt $word)
757             _ovs_vsctl_detect_nospace $tmp
758             completion="${completion} ${tmp#*EO}"
759         fi
760         if [ $valid_opts == true ]; then
761             tmp=$(_ovs_vsctl_bashcomp_localopt "$given_opts" $word)
762             _ovs_vsctl_detect_nospace $tmp
763             completion="${completion} ${tmp#*EO}"
764             if [ $index -lt $COMP_CWORD ] \
765                && _ovs_vsctl_detect_nonzero_completions "$tmp"; then
766                 valid_globals=false
767                 given_opts="${given_opts} ${word}"
768             fi
769         fi
770         if [ $valid_commands = true ]; then
771             tmp=$(_ovs_vsctl_bashcomp_command "$given_opts" $word)
772             _ovs_vsctl_detect_nospace $tmp
773             completion="${completion} ${tmp#*EO}"
774             if [ $index -lt $COMP_CWORD ] \
775                && _ovs_vsctl_detect_nonzero_completions "$tmp"; then
776                 valid_globals=false
777                 valid_opts=false
778                 valid_commands=false
779                 cmd_pos=0
780                 raw_cmd=$(_ovs_vsctl_expand_command "$word")
781                 readarray -t cmd_args <<< "$raw_cmd"
782             fi
783         fi
784         if [ "$word" = "--" ] && [ $index -lt $COMP_CWORD ]; then
785             # Empty the parsed args array.
786             _OVS_VSCTL_PARSED_AGS=()
787             cmd_pos=-1
788             # No longer allow global options after '--'.
789             valid_globals=false
790             valid_opts=true
791             valid_commands=true
792             given_opts=""
793         fi
794         completion="$(sort -u <<< "$(tr ' ' '\n' <<< ${completion})")"
795         if [ $index -eq $COMP_CWORD ]; then
796             if [ "$test" = "true" ]; then
797                 completion="$(_ovs_vsctl_trim_compreply "$word" ":=" ${completion} | \
798                               tr ' ' '\n')"
799                 if [ "${_OVS_VSCTL_COMP_NOSPACE}" = "true" ]; then
800                     printf "%s" "$completion" | sed -e '/^$/d'
801                 else
802                     printf "%s" "$completion" | sed -e '/^$/d; s/$/ /g'
803                 fi
804                 printf "\n"
805             else
806                 if [ "${_OVS_VSCTL_COMP_NOSPACE}" = "true" ]; then
807                     compopt -o nospace
808                     COMPREPLY=( $(compgen -W "${completion}" -- $word) )
809                 else
810                     compopt +o nospace
811                     COMPREPLY=( $(compgen -W "${completion}" -- $word) )
812                 fi
813                 COMPREPLY=( $(_ovs_vsctl_trim_compreply "$word" \
814                               "${COMP_WORDBREAKS}" ${COMPREPLY[@]}) )
815             fi
816         fi
817         index=$(($index+1))
818     done
819 }
820
821 if [ "$1" = "test" ]; then
822     _ovs_vsctl_bashcomp "$@"
823 else
824     complete -F _ovs_vsctl_bashcomp ovs-vsctl
825 fi