netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 case $0 in
17     */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
18     *) dir0=./ ;;
19 esac
20 . "$dir0/ovs-lib" || exit 1
21
22 for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
23     case :$PATH: in
24         *:$dir:*) ;;
25         *) PATH=$PATH:$dir ;;
26     esac
27 done
28
29 ## ----- ##
30 ## start ##
31 ## ----- ##
32
33 # Keep track of removed vports so we can reload them if needed
34 removed_vports=""
35
36 insert_mods () {
37     # Try loading openvswitch again.
38     action "Inserting openvswitch module" modprobe openvswitch
39
40     for vport in $removed_vports; do
41         # Don't treat failures to load vports as fatal error
42         action "Inserting $vport module" modprobe $vport || true
43     done
44 }
45
46 insert_mod_if_required () {
47     # If this kernel has no module support, expect we're done.
48     if test ! -e /proc/modules
49     then
50         log_success_msg "Kernel has no loadable module support. Skipping modprobe"
51         return 0
52     fi
53
54     # If openvswitch is already loaded then we're done.
55     test -e /sys/module/openvswitch -o -e /sys/module/openvswitch_mod && \
56      return 0
57
58     # Load openvswitch.  If that's successful then we're done.
59     insert_mods && return 0
60
61     # If the bridge module is loaded, then that might be blocking
62     # openvswitch.  Try to unload it, if there are no bridges.
63     test -e /sys/module/bridge || return 1
64     bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
65     if test "$bridges" != "*"; then
66         log_warning_msg "not removing bridge module because bridges exist ($bridges)"
67         return 1
68     fi
69     action "removing bridge module" rmmod bridge || return 1
70
71     # Try loading openvswitch again.
72     insert_mods
73 }
74
75 ovs_vsctl () {
76     ovs-vsctl --no-wait "$@"
77 }
78
79 set_system_ids () {
80     set ovs_vsctl set Open_vSwitch .
81
82     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
83     set "$@" ovs-version="$OVS_VERSION"
84
85     case $SYSTEM_ID in
86         random)
87             id_file=$etcdir/system-id.conf
88             uuid_file=$etcdir/install_uuid.conf
89             if test -e "$id_file"; then
90                 SYSTEM_ID=`cat "$id_file"`
91             elif test -e "$uuid_file"; then
92                 # Migrate from old file name.
93                 . "$uuid_file"
94                 SYSTEM_ID=$INSTALLATION_UUID
95                 echo "$SYSTEM_ID" > "$id_file"
96             elif SYSTEM_ID=`uuidgen`; then
97                 echo "$SYSTEM_ID" > "$id_file"
98             else
99                 log_failure_msg "missing uuidgen, could not generate system ID"
100             fi
101             ;;
102
103         '')
104             log_failure_msg "system ID not configured, please use --system-id"
105             ;;
106
107         *)
108             ;;
109     esac
110     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
111
112     if test X"$SYSTEM_TYPE" != X; then
113         set "$@" system-type="\"$SYSTEM_TYPE\""
114     else
115         log_failure_msg "no default system type, please use --system-type"
116     fi
117
118     if test X"$SYSTEM_VERSION" != X; then
119         set "$@" system-version="\"$SYSTEM_VERSION\""
120     else
121         log_failure_msg "no default system version, please use --system-version"
122     fi
123
124     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
125 }
126
127 check_force_cores () {
128     if test X"$FORCE_COREFILES" = Xyes; then
129         ulimit -c 67108864
130     fi
131 }
132
133 del_transient_ports () {
134     for port in `ovs-vsctl --bare -- --columns=name find port other_config:transient=true`; do
135         ovs_vsctl -- del-port "$port"
136     done
137 }
138
139 start_ovsdb () {
140     check_force_cores
141
142     if daemon_is_running ovsdb-server; then
143         log_success_msg "ovsdb-server is already running"
144     else
145         # Create initial database or upgrade database schema.
146         upgrade_db $DB_FILE $DB_SCHEMA || return 1
147
148         # Start ovsdb-server.
149         set ovsdb-server "$DB_FILE"
150         for db in $EXTRA_DBS; do
151             case $db in
152                 /*) ;;
153                 *) db=$dbdir/$db ;;
154             esac
155
156             if test ! -f "$db"; then
157                 log_warning_msg "$db (from \$EXTRA_DBS) does not exist."
158             elif ovsdb-tool db-version "$db" >/dev/null; then
159                 set "$@" "$db"
160             else
161                 log_warning_msg "$db (from \$EXTRA_DBS) cannot be read as a database (see error message above)"
162             fi
163         done
164         set "$@" -vconsole:emer -vsyslog:err -vfile:info
165         set "$@" --remote=punix:"$DB_SOCK"
166         set "$@" --private-key=db:Open_vSwitch,SSL,private_key
167         set "$@" --certificate=db:Open_vSwitch,SSL,certificate
168         set "$@" --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
169         start_daemon "$OVSDB_SERVER_PRIORITY" "$OVSDB_SERVER_WRAPPER" "$@" \
170             || return 1
171
172         # Initialize database settings.
173         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
174             || return 1
175         set_system_ids || return 1
176         if test X"$DELETE_BRIDGES" = Xyes; then
177             for bridge in `ovs_vsctl list-br`; do
178                 ovs_vsctl del-br $bridge
179             done
180         fi
181         if test X"$DELETE_TRANSIENT_PORTS" = Xyes; then
182             del_transient_ports
183         fi
184     fi
185 }
186
187 add_managers () {
188     # Now that ovs-vswitchd has started and completed its initial
189     # configuration, tell ovsdb-server to conenct to the remote managers.  We
190     # used to do this at ovsdb-server startup time, but waiting for
191     # ovs-vswitchd to finish configuring means that remote managers see less
192     # churn in the database at startup or restart.  (For example, managers
193     # won't briefly see empty datapath-id or ofport columns for records that
194     # exist at startup.)
195     action "Enabling remote OVSDB managers" \
196         ovs-appctl -t ovsdb-server ovsdb-server/add-remote \
197             db:Open_vSwitch,Open_vSwitch,manager_options
198 }
199
200 start_forwarding () {
201     check_force_cores
202
203     insert_mod_if_required || return 1
204
205     if daemon_is_running ovs-vswitchd; then
206         log_success_msg "ovs-vswitchd is already running"
207     else
208         # Increase the limit on the number of open file descriptors.
209         # On Linux, ovs-vswitchd needs about three file descriptors
210         # per bridge and "n-handler-threads" file descriptors per bridge
211         # port, so this allows a very large number of bridges and ports.
212         MAXFD=65535
213         if [ $(ulimit -n) -lt $MAXFD ]; then
214             ulimit -n $MAXFD
215         fi
216
217             # Start ovs-vswitchd.
218             set ovs-vswitchd unix:"$DB_SOCK"
219             set "$@" -vconsole:emer -vsyslog:err -vfile:info
220             if test X"$MLOCKALL" != Xno; then
221                 set "$@" --mlockall
222             fi
223             start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
224     fi
225 }
226
227 ## ---- ##
228 ## stop ##
229 ## ---- ##
230
231 stop_ovsdb () {
232     stop_daemon ovsdb-server
233 }
234
235 stop_forwarding () {
236     stop_daemon ovs-vswitchd
237 }
238
239 ## ----------------- ##
240 ## force-reload-kmod ##
241 ## ----------------- ##
242
243 internal_interfaces () {
244     # Outputs a list of internal interfaces:
245     #
246     #   - There is an internal interface for every bridge, whether it
247     #     has an Interface record or not and whether the Interface
248     #     record's 'type' is properly set or not.
249     #
250     #   - There is an internal interface for each Interface record whose
251     #     'type' is 'internal'.
252     #
253     # But ignore interfaces that don't really exist.
254     for d in `(ovs_vsctl --bare \
255                 -- --columns=name find Interface type=internal \
256                     -- list-br) | sort -u`
257     do
258         if test -e "/sys/class/net/$d"; then
259                 printf "%s " "$d"
260             fi
261     done
262 }
263
264 ovs_save () {
265     bridges=`ovs_vsctl -- --real list-br`
266     if [ -n "${bridges}" ] && \
267         "$datadir/scripts/ovs-save" "$1" ${bridges} > "$2"; then
268         chmod +x "$2"
269         return 0
270     fi
271     [ -z "${bridges}" ] && return 0
272 }
273
274 save_ofports_if_required () {
275     # Save OpenFlow port numbers if we are upgrading from a pre-1.10 branch.
276     #
277     # (Versions 1.10 and later save OpenFlow port numbers without assistance,
278     # so we don't have to do anything for them.
279     case `ovs-appctl version | sed 1q` in
280         "ovs-vswitchd (Open vSwitch) 1."[0-9].*)
281             action "Saving ofport values" ovs_save save-ofports \
282                 "${script_ofports}"
283             ;;
284     esac
285 }
286
287 save_flows_if_required () {
288     if test X"$DELETE_BRIDGES" != Xyes; then
289         action "Saving flows" ovs_save save-flows "${script_flows}"
290     fi
291 }
292
293 save_interfaces () {
294     "$datadir/scripts/ovs-save" save-interfaces ${ifaces} \
295         > "${script_interfaces}"
296 }
297
298 restore_ofports () {
299     [ -x "${script_ofports}" ] && \
300         action "Restoring ofport values" "${script_ofports}"
301 }
302
303 flow_restore_wait () {
304     ovs_vsctl set open_vswitch . other_config:flow-restore-wait="true"
305 }
306
307 flow_restore_complete () {
308     ovs_vsctl --if-exists remove open_vswitch . other_config \
309         flow-restore-wait="true"
310 }
311
312 restore_flows () {
313     [ -x "${script_flows}" ] && \
314         action "Restoring saved flows" "${script_flows}"
315 }
316
317 restore_interfaces () {
318     [ ! -x "${script_interfaces}" ] && return 0
319     action "Restoring interface configuration" "${script_interfaces}"
320     rc=$?
321     if test $rc = 0; then
322         level=debug
323     else
324         level=err
325     fi
326     log="logger -p daemon.$level -t ovs-save"
327     $log "interface restore script exited with status $rc:"
328     $log -f "$script_interfaces"
329 }
330
331 init_restore_scripts () {
332     script_interfaces=`mktemp`
333     script_flows=`mktemp`
334     script_ofports=`mktemp`
335     trap 'rm -f "${script_interfaces}" "${script_flows}" "${script_ofports}"' 0
336 }
337
338 force_reload_kmod () {
339     ifaces=`internal_interfaces`
340     action "Detected internal interfaces: $ifaces" true
341
342     init_restore_scripts
343     save_flows_if_required
344     save_ofports_if_required
345
346     # Restart the database first, since a large database may take a
347     # while to load, and we want to minimize forwarding disruption.
348     stop_ovsdb
349     start_ovsdb
350
351     # Restore of ofports should happen before vswitchd is restarted.
352     restore_ofports
353
354     stop_forwarding
355
356     if action "Saving interface configuration" save_interfaces; then
357         :
358     else
359         log_warning_msg "Failed to save configuration, not replacing kernel module"
360         start_forwarding
361         add_managers
362         exit 1
363     fi
364     chmod +x "$script_interfaces"
365
366     for dp in `ovs-dpctl dump-dps`; do
367         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
368     done
369
370     for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
371         action "Removing $vport module" rmmod $vport
372         if ! grep -q $vport /proc/modules; then
373             removed_vports="$removed_vports $vport"
374         fi
375     done
376
377     # try both old and new names in case this is post upgrade
378     if test -e /sys/module/openvswitch_mod; then
379         action "Removing openvswitch module" rmmod openvswitch_mod
380     elif test -e /sys/module/openvswitch; then
381         action "Removing openvswitch module" rmmod openvswitch
382     fi
383
384     # Start vswitchd by asking it to wait till flow restore is finished.
385     flow_restore_wait
386     start_forwarding
387
388     # Restore saved flows and inform vswitchd that we are done.
389     restore_flows
390     flow_restore_complete
391     add_managers
392
393     restore_interfaces
394
395     "$datadir/scripts/ovs-check-dead-ifs"
396 }
397
398 ## ------- ##
399 ## restart ##
400 ## ------- ##
401
402 save_interfaces_if_required () {
403     # Save interfaces if we are upgrading from a pre-1.10 branch.
404     case `ovs-appctl version | sed 1q` in
405         "ovs-vswitchd (Open vSwitch) 1."[0-9].*)
406             ifaces=`internal_interfaces`
407             action "Detected internal interfaces: $ifaces" true
408             if action "Saving interface configuration" save_interfaces; then
409                 chmod +x "$script_interfaces"
410             fi
411             ;;
412     esac
413 }
414
415 restart () {
416     if daemon_is_running ovsdb-server && daemon_is_running ovs-vswitchd; then
417         init_restore_scripts
418         save_interfaces_if_required
419         save_flows_if_required
420         save_ofports_if_required
421     fi
422
423     # Restart the database first, since a large database may take a
424     # while to load, and we want to minimize forwarding disruption.
425     stop_ovsdb
426     start_ovsdb
427
428     # Restore of ofports, if required, should happen before vswitchd is
429     # restarted.
430     restore_ofports
431
432     stop_forwarding
433
434     # Start vswitchd by asking it to wait till flow restore is finished.
435     flow_restore_wait
436     start_forwarding
437
438     # Restore saved flows and inform vswitchd that we are done.
439     restore_flows
440     flow_restore_complete
441     add_managers
442
443     # Restore the interfaces if required. Return true even if restore fails.
444     restore_interfaces || true
445 }
446
447 ## --------------- ##
448 ## enable-protocol ##
449 ## --------------- ##
450
451 enable_protocol () {
452     # Translate the protocol name to a number, because "iptables -n -L" prints
453     # some protocols by name (despite the -n) and therefore we need to look for
454     # both forms.
455     #
456     # (iptables -S output is more uniform but old iptables doesn't have it.)
457     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
458     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
459         log_failure_msg "unknown protocol $PROTOCOL"
460         return 1
461     fi
462
463     name=$PROTOCOL
464     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
465     insert="iptables -I INPUT -p $PROTOCOL"
466     if test X"$DPORT" != X; then
467         name="$name to port $DPORT"
468         match="$match && /dpt:$DPORT/"
469         insert="$insert --dport $DPORT"
470     fi
471     if test X"$SPORT" != X; then
472         name="$name from port $SPORT"
473         match="$match && /spt:$SPORT/"
474         insert="$insert --sport $SPORT"
475     fi
476     insert="$insert -j ACCEPT"
477
478     if (iptables -n -L INPUT) >/dev/null 2>&1; then
479         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
480         then
481             # There's already a rule for this protocol.  Don't override it.
482             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
483         else
484             action "Enabling $name with iptables" $insert
485         fi
486     elif (iptables --version) >/dev/null 2>&1; then
487         action "cannot list iptables rules, not adding a rule for $name"
488     else
489         action "iptables binary not installed, not adding a rule for $name"
490     fi
491 }
492
493 ## ---- ##
494 ## main ##
495 ## ---- ##
496
497 set_defaults () {
498     SYSTEM_ID=
499
500     DELETE_BRIDGES=no
501     DELETE_TRANSIENT_PORTS=no
502
503     DAEMON_CWD=/
504     FORCE_COREFILES=yes
505     MLOCKALL=yes
506     OVSDB_SERVER_PRIORITY=-10
507     OVS_VSWITCHD_PRIORITY=-10
508     OVSDB_SERVER_WRAPPER=
509     OVS_VSWITCHD_WRAPPER=
510
511     DB_FILE=$dbdir/conf.db
512     DB_SOCK=$rundir/db.sock
513     DB_SCHEMA=$datadir/vswitch.ovsschema
514     EXTRA_DBS=
515
516     PROTOCOL=gre
517     DPORT=
518     SPORT=
519
520     type_file=$etcdir/system-type.conf
521     version_file=$etcdir/system-version.conf
522
523     if test -e "$type_file" ; then
524         SYSTEM_TYPE=`cat $type_file`
525         SYSTEM_VERSION=`cat $version_file`
526     elif (lsb_release --id) >/dev/null 2>&1; then
527         SYSTEM_TYPE=`lsb_release --id -s`
528         system_release=`lsb_release --release -s`
529         system_codename=`lsb_release --codename -s`
530         SYSTEM_VERSION="${system_release}-${system_codename}"
531     else
532         SYSTEM_TYPE=unknown
533         SYSTEM_VERSION=unknown
534     fi
535 }
536
537 usage () {
538     set_defaults
539     cat <<EOF
540 $0: controls Open vSwitch daemons
541 usage: $0 [OPTIONS] COMMAND
542
543 This program is intended to be invoked internally by Open vSwitch startup
544 scripts.  System administrators should not normally invoke it directly.
545
546 Commands:
547   start              start Open vSwitch daemons
548   stop               stop Open vSwitch daemons
549   restart            stop and start Open vSwitch daemons
550   status             check whether Open vSwitch daemons are running
551   version            print versions of Open vSwitch daemons
552   load-kmod          insert modules if not already present
553   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
554                      module, reload kernel module, start OVS, restore state
555   enable-protocol    enable protocol specified in options with iptables
556   help               display this help message
557
558 One of the following options is required for "start", "restart" and "force-reload-kmod":
559   --system-id=UUID   set specific ID to uniquely identify this system
560   --system-id=random  use a random but persistent UUID to identify this system
561
562 Other important options for "start", "restart" and "force-reload-kmod":
563   --system-type=TYPE  set system type (e.g. "XenServer")
564   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
565   --external-id="key=value"
566                      add given key-value pair to Open_vSwitch external-ids
567   --delete-bridges   delete all bridges just before starting ovs-vswitchd
568
569 Less important options for "start", "restart" and "force-reload-kmod":
570   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
571   --no-force-corefiles           do not force on core dumps for OVS daemons
572   --no-mlockall                  do not lock all of ovs-vswitchd into memory
573   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
574   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
575
576 Debugging options for "start", "restart" and "force-reload-kmod":
577   --ovsdb-server-wrapper=WRAPPER
578   --ovs-vswitchd-wrapper=WRAPPER
579   --ovs-vswitchd-wrapper=WRAPPER
580      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
581
582 File location options:
583   --db-file=FILE     database file name (default: $DB_FILE)
584   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
585   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
586
587 Options for "enable-protocol":
588   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
589   --sport=PORT       source port to match (for tcp or udp protocol)
590   --dport=PORT       ddestination port to match (for tcp or udp protocol)
591
592 Other options:
593   -h, --help                  display this help message
594   -V, --version               display version information
595
596 Default directories with "configure" option and environment variable override:
597   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
598   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
599   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
600   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
601   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
602   user binaries: @bindir@ (--bindir, OVS_BINDIR)
603   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
604
605 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
606 EOF
607
608     exit 0
609 }
610
611 set_option () {
612     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
613     eval set=\${$var+yes}
614     eval old_value=\$$var
615     if test X$set = X || \
616         (test $type = bool && \
617         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
618         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
619         return
620     fi
621     eval $var=\$value
622 }
623
624 daemons () {
625     echo ovsdb-server ovs-vswitchd
626 }
627
628 set_defaults
629 extra_ids=
630 command=
631 for arg
632 do
633     case $arg in
634         -h | --help)
635             usage
636             ;;
637         -V | --version)
638             echo "$0 (Open vSwitch) $VERSION"
639             exit 0
640             ;;
641         --external-id=*)
642             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
643             case $value in
644                 *=*)
645                     extra_ids="$extra_ids external-ids:$value"
646                     ;;
647                 *)
648                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
649                     exit 1
650                     ;;
651             esac
652             ;;
653         --[a-z]*=*)
654             option=`expr X"$arg" : 'X--\([^=]*\)'`
655             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
656             type=string
657             set_option
658             ;;
659         --no-[a-z]*)
660             option=`expr X"$arg" : 'X--no-\(.*\)'`
661             value=no
662             type=bool
663             set_option
664             ;;
665         --[a-z]*)
666             option=`expr X"$arg" : 'X--\(.*\)'`
667             value=yes
668             type=bool
669             set_option
670             ;;
671         -*)
672             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
673             exit 1
674             ;;
675         *)
676             if test X"$command" = X; then
677                 command=$arg
678             else
679                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
680                 exit 1
681             fi
682             ;;
683     esac
684 done
685 case $command in
686     start)
687         start_ovsdb || exit 1
688         start_forwarding
689         add_managers
690         ;;
691     stop)
692         stop_forwarding
693         stop_ovsdb
694         ;;
695     restart)
696         restart
697         ;;
698     status)
699         rc=0
700         for daemon in `daemons`; do
701             daemon_status $daemon || rc=$?
702         done
703         exit $rc
704         ;;
705     version)
706         for daemon in `daemons`; do
707             $daemon --version
708         done
709         ;;
710     force-reload-kmod)
711             force_reload_kmod
712         ;;
713     load-kmod)
714         insert_mod_if_required
715         ;;
716     enable-protocol)
717         enable_protocol
718         ;;
719     help)
720         usage
721         ;;
722     '')
723         echo >&2 "$0: missing command name (use --help for help)"
724         exit 1
725         ;;
726     *)
727         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
728         exit 1
729         ;;
730 esac