]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/bsdconfig/share/device.subr
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.sbin / bsdconfig / share / device.subr
1 if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
2 #
3 # Copyright (c) 2012-2013 Devin Teske
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 # SUCH DAMAGE.
26 #
27 # $FreeBSD$
28 #
29 ############################################################ INCLUDES
30
31 BSDCFG_SHARE="/usr/share/bsdconfig"
32 . $BSDCFG_SHARE/common.subr || exit 1
33 f_dprintf "%s: loading includes..." device.subr
34 f_include $BSDCFG_SHARE/dialog.subr
35 f_include $BSDCFG_SHARE/strings.subr
36 f_include $BSDCFG_SHARE/struct.subr
37
38 BSDCFG_LIBE="/usr/libexec/bsdconfig"
39 f_include_lang $BSDCFG_LIBE/include/messages.subr
40
41 ############################################################ GLOBALS
42
43 DEVICES=
44 DEVICE_NAMES=
45
46 # A "device" from sysinstall's point of view
47 f_struct_define DEVICE \
48         name            \
49         desc            \
50         devname         \
51         type            \
52         enabled         \
53         init            \
54         get             \
55         shutdown        \
56         flags           \
57         private         \
58         volume  
59
60 # Network devices have their `private' property set to this
61 f_struct_define DEVICE_INFO \
62         use_rtsol use_dhcp ipaddr ipv6addr netmask extras
63
64 setvar DEVICE_TYPE_NONE         1
65 setvar DEVICE_TYPE_DISK         2
66 setvar DEVICE_TYPE_FLOPPY       3
67 setvar DEVICE_TYPE_FTP          4
68 setvar DEVICE_TYPE_NETWORK      5
69 setvar DEVICE_TYPE_CDROM        6
70 setvar DEVICE_TYPE_USB          7
71 setvar DEVICE_TYPE_DOS          8
72 setvar DEVICE_TYPE_UFS          9
73 setvar DEVICE_TYPE_NFS          10
74 setvar DEVICE_TYPE_ANY          11
75 setvar DEVICE_TYPE_HTTP_PROXY   12
76 setvar DEVICE_TYPE_HTTP         13
77
78 #
79 # Default behavior is to call f_device_get_all() automatically when loaded.
80 #
81 : ${DEVICE_SELF_SCAN_ALL=1}
82
83 ############################################################ FUNCTIONS
84
85 # f_device_try $name [$i [$var_path]]
86 #
87 # Test a particular device. If $i is given, then $name is expected to contain a
88 # single "%d" where $i will be inserted using printf. If $var_path is given,
89 # it is used as a variable name to provide the caller the device pathname.
90 #
91 # Returns success if the device path exists and is a cdev.
92 #
93 f_device_try()
94 {
95         local name="$1" i="$2" var_path="$3" unit
96         if [ "$i" ]; then
97                 unit=$( printf "$name" "$i" )
98         else
99                 unit="$name"
100         fi
101         case "$unit" in
102         /dev/*) : good ;; # already qualified
103         *) unit="/dev/$unit" ;;
104         esac
105         [ "$var_path" ] && setvar "$var_path" "$unit"
106         f_dprintf "f_device_try: making sure %s is a device node" "$unit"
107         if [ -c "$unit" ]; then
108                 f_dprintf "f_device_try: %s is a cdev [good]" "$unit"
109                 return $SUCCESS
110         else
111                 f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit"
112                 return $FAILURE
113         fi
114 }
115
116 # f_device_register $name $desc $devname $type $enabled $init_function \
117 #                   $get_function $shutdown_function $private
118 #
119 # Register a device. A `structure' (see struct.subr) is created with the name
120 # device_$name (so make sure $name contains only alpha-numeric characters or
121 # the underscore, `_'). The remaining arguments after $name correspond to the
122 # properties of the `DEVICE' structure-type (defined above).
123 #
124 # If not already registered, the device is then appended to the DEVICES
125 # environment variable, a space-separated list of all registered devices.
126 #
127 f_device_register()
128 {
129         local name="$1" desc="$2" devname="$3" type="$4" enabled="$5"
130         local init_func="$6" get_func="$7" shutdown_func="$8" private="$9"
131
132         f_struct_new DEVICE "device_$name" || return $FAILURE
133         device_$name set name     "$name"
134         device_$name set desc     "$desc"
135         device_$name set devname  "$devname"
136         device_$name set type     "$type"
137         device_$name set enabled  "$enabled"
138         device_$name set init     "$init_func"
139         device_$name set get      "$get_func"
140         device_$name set shutdown "$shutdown_func"
141         device_$name set private  "$private"
142
143         # Scan our global register to see if it needs ammending
144         local dev found=
145         for dev in $DEVICES; do
146                 [ "$dev" = "$name" ] || continue
147                 found=1 && break
148         done
149         [ "$found" ] || DEVICES="$DEVICES $name"
150
151         return $SUCCESS
152 }
153
154 # f_device_reset
155 #
156 # Reset the registered device chain.
157 #
158 f_device_reset()
159 {
160         local dev
161         for dev in $DEVICES; do
162                 f_device_shutdown $dev
163
164                 #
165                 # XXX this potentially leaks $dev->private if it's being
166                 # used to point to something dynamic, but you're not supposed
167                 # to call this routine at such times that some open instance
168                 # has its private member pointing somewhere anyway. XXX
169                 #
170                 f_struct_free device_$dev
171         done
172         DEVICES=
173 }
174
175 # f_device_get_all
176 #
177 # Get all device information for devices we have attached.
178 #
179 f_device_get_all()
180 {
181         local devname desc
182
183         f_dprintf "f_device_get_all: Probing devices..."
184         f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
185
186         # First go for the network interfaces
187         for devname in $( ifconfig -l ); do
188                 # Eliminate network devices that don't make sense
189                 case "$devname" in
190                 lo*) continue ;;
191                 esac
192
193                 # Try and find its description
194                 f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc
195
196                 f_dprintf "Found a network device named %s" "$devname"
197                 f_device_register $devname \
198                         "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \
199                         f_media_init_network "" f_media_shutdown_network ""
200         done
201
202         # Next, try to find all the types of devices one might use
203         # as a media source for content
204         #
205
206         local dev desc type max n=0
207         for dev in $DEVICE_NAMES; do
208                 n=$(( $n + 1 ))
209                 # Get the desc, type, and max (with debugging disabled)
210                 # NOTE: Bypassing f_device_name_get() for efficiency
211                 debug= f_getvar _device_desc$n desc
212                 debug= f_getvar _device_type$n type
213                 debug= f_getvar _device_max$n max
214
215                 local k=0
216                 while [ $k -lt ${max:-0} ]; do
217                         i=$k k=$(( $k + 1 ))
218                         devname=""
219                         case "$type" in
220                         $DEVICE_TYPE_CDROM)
221                                 f_device_try "$dev" "$i" devname || continue
222                                 f_device_register "${devname##*/}" "$desc" \
223                                         "$devname" $DEVICE_TYPE_CDROM 1 \
224                                         f_media_init_cdrom f_media_get_cdrom \
225                                         f_media_shutdown_cdrom ""
226                                 f_dprintf "Found a CDROM device for %s" \
227                                           "$devname"
228                                 ;;
229                         $DEVICE_TYPE_FLOPPY)
230                                 f_device_try "$dev" "$i" devname || continue
231                                 f_device_register "${devname##*/}" "$desc" \
232                                         "$devname" $DEVICE_TYPE_FLOPPY 1 \
233                                         f_media_init_floppy \
234                                         f_media_get_floppy \
235                                         f_media_shutdown_floppy ""
236                                 f_dprintf "Found a floppy device for %s" \
237                                           "$devname"
238                                 ;;
239                         $DEVICE_TYPE_USB)
240                                 f_device_try "$dev" "$i" devname || continue
241                                 f_device_register "${devname##*/}" "$desc" \
242                                         "$devname" $DEVICE_TYPE_USB 1 \
243                                         f_media_init_usb f_media_get_usb \
244                                         f_media_shutdown_usb ""
245                                 f_dprintf "Found a USB disk for %s" "$devname"
246                                 ;;
247                         esac
248                 done
249         done
250
251         # Register ISO9660 providers as CDROM devices
252         for devname in /dev/iso9660/*; do
253                 f_device_try "$devname" || continue
254                 f_device_register "${devname##*/}" "ISO9660 file system" \
255                         "$devname" $DEVICE_TYPE_CDROM 1 \
256                         f_media_init_cdrom f_media_get_cdrom \
257                         f_media_shutdown_cdrom ""
258                 f_dprintf "Found a CDROM device for %s" "$devname"
259         done
260
261         # Scan for mdconfig(8)-created md(4) devices
262         local filename
263         for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do
264                 f_device_try "$devname" || continue
265
266                 # See if the md(4) device is a vnode type backed by a file
267                 filename=$( sysctl kern.geom.conftxt |
268                         awk -v devname="${devname##*/}" \
269                         '
270                                 ( $2 == "MD" ) && \
271                                 ( $3 == devname ) && \
272                                 ( $(NF-2) == "vnode" ) && \
273                                 ( $(NF-1) == "file" ) \
274                                 {
275                                         print $NF
276                                 }
277                         ' )
278                 case "$filename" in
279                 *.iso) # Register the device as an ISO9660 provider
280                         f_device_register "${devname##*/}" \
281                                 "md(4) vnode file system" \
282                                 "$devname" $DEVICE_TYPE_CDROM 1 \
283                                 f_media_init_cdrom f_media_get_cdrom \
284                                 f_media_shutdown_cdrom ""
285                         f_dprintf "Found a CDROM device for %s" "$devname"
286                         ;;
287                 esac
288         done
289
290         # Finally go get the disks and look for partitions to register
291         local diskname slices index type rest slice part
292         for diskname in $( sysctl -n kern.disks ); do
293
294                 case "$diskname" in
295                 cd*)
296                         # XXX
297                         #  Due to unknown reasons, kern.disks returns SCSI
298                         # CDROM as a valid disk. This will prevent bsdconfig
299                         # from presenting SCSI CDROMs as available disks in
300                         # various menus. Why GEOM treats SCSI CDROM as a disk
301                         # is beyond me and that should be investigated.
302                         # For temporary workaround, ignore SCSI CDROM device.
303                         #
304                         continue ;;
305                 esac
306
307                 # Try to create a list of partitions and their types,
308                 # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06").
309                 if ! slices=$( fdisk -p "$diskname" 2> /dev/null |
310                         awk '( $1 == "p" ) { print $2","$3 }' )
311                 then
312                         f_dprintf "Unable to open disk %s" "$diskname"
313                         continue
314                 fi
315
316                 f_device_register "$diskname" "" \
317                                   "/dev/$diskname" $DEVICE_TYPE_DISK 0
318                 f_dprintf "Found a disk device named %s" "$diskname"
319
320                 # Look for existing partitions to register
321                 for slice in $slices; do
322                         index="${slice%%,*}" type="${slice#*,}"
323                         slice=${diskname}s$index
324                         case "$type" in
325                         0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef)
326                                 # DOS partitions to add as "DOS media devices"
327                                 f_device_register "$slice" "" \
328                                         "/dev/$slice" $DEVICE_TYPE_DOS 1 \
329                                         f_media_init_dos f_media_get_dos \
330                                         f_media_shutdown_dos ""
331                                 f_dprintf "Found a DOS partition %s" "$slice"
332                                 ;;
333                         0xa5) # FreeBSD partition
334                                 for part in $(
335                                         bsdlabel -r $slice 2> /dev/null |
336                                                 awk -v slice="$slice" '
337                                                 ( $1 ~ /[abdefgh]:/ ) {
338                                                         printf "%s%s\n",
339                                                                slice,
340                                                                substr($1,1,1)
341                                                 }'
342                                 ); do
343                                         f_quietly dumpfs -m /dev/$part ||
344                                                 continue
345                                         f_device_register \
346                                                 "$part" "" "/dev/$part" \
347                                                 $DEVICE_TYPE_UFS 1 \
348                                                 f_media_init_ufs \
349                                                 f_media_get_ufs \
350                                                 f_media_shutdown_ufs ""
351                                         f_dprintf "Found a UFS partition %s" \
352                                                   "$part"
353                                 done # parts
354                                 ;;
355                         esac
356                 done # slices
357
358         done # disks
359 }
360
361 # f_device_name_get $type $name type|desc|max [$var_to_set]
362 #
363 # Fetch the device type (type), description (desc), or maximum number of
364 # devices to scan for (max) associated with device $name and $type. If $type is
365 # either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
366 # Returns success if a match was found, otherwise failure.
367 #
368 # If $var_to_set is missing or NULL, the device name is printed to standard out
369 # for capturing in a sub-shell (which is less-recommended because of
370 # performance degredation; for example, when called in a loop).
371 #
372 f_device_name_get()
373 {
374         local __type="$1" __name="$2" __prop="$3" __var_to_set="$4"
375         local __dev __devtype __n=0
376
377         # Return failure if no $name or $prop is an unknown property
378         [ "$__name" ] || return $FAILURE
379         case "$__prop" in type|desc|max) : good ;;
380         *) return $FAILURE; esac
381
382         [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type=
383         for __dev in $DEVICE_NAMES; do
384                 __n=$(( $__n + 1 ))
385                 [ "$__dev" = "$__name" ] || continue
386                 f_getvar _device_type$__n __devtype
387                 [ "${__type:-$__devtype}" = "$__devtype" ] || continue
388                 f_getvar _device_$__prop$__n $__var_to_set
389                 return $?
390         done
391         return $FAILURE
392 }
393
394 # f_device_name_set $type $name $desc [$max]
395 #
396 # Store a description (desc) and [optionally] maximum number of devices to scan
397 # for (max) in-association with device $type and $name. Returns success unless
398 # $name is NULL or missing. Use the f_device_name_get() routine with the same
399 # $name and optionally $type to retrieve one of type, desc, or max properties.
400 #
401 f_device_name_set()
402 {
403         local type="$1" name="$2" desc="$3" max="$4"
404         local dev devtype n=0 found=
405         [ "$name" ] || return $FAILURE
406         for dev in $DEVICE_NAMES; do
407                 n=$(( $n + 1 ))
408                 [ "$dev" = "$name" ] || continue
409                 if f_getvar _device_type$n devtype; then
410                         # Allow multiple entries with same name but diff type
411                         [ "$devtype" = "$type" ] || continue
412                 fi
413                 found=1 && break
414         done
415         if [ ! "$found" ]; then
416                 DEVICE_NAMES="$DEVICE_NAMES $name"
417                 n=$(( $n + 1 ))
418         fi
419         setvar _device_type$n "$type"
420         setvar _device_desc$n "$desc"
421         [ "${4+set}" ] && setvar _device_max$n "$max"
422         return $SUCCESS
423 }
424
425 # f_device_desc $device_name $device_type [$var_to_set]
426 #
427 # Print a description for a device name (eg., `fxp0') given a specific device
428 # type/class.
429 #
430 # If $var_to_set is missing or NULL, the device description is printed to
431 # standard out for capturing in a sub-shell (which is less-recommended because
432 # of performance degredation; for example, when called in a loop).
433 #
434 f_device_desc()
435 {
436         local __name="$1" __type="$2" __var_to_set="$3"
437         local __devname __devunit __cp
438
439         # Check variables
440         [ "$__name" ] || return $SUCCESS
441         [ "$__type" = "$DEVICE_TYPE_ANY" ] && type=
442         [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; }
443
444         #
445         # Return sysctl MIB dev.NAME.UNIT.%desc if it exists,
446         # otherwise fall through to below static list.
447         #
448         if f_have sysctl; then
449                 __devname="${__name%%[0-9]*}"
450                 __devunit="${__name#$__devname}"
451                 __devunit="${__devunit%%[!0-9]*}"
452                 if [ "$__var_to_set" ]; then
453                         if __cp=$(
454                                 sysctl -n "dev.$__devname.$__devunit.%desc" \
455                                 2> /dev/null
456                         ); then
457                                 setvar "$__var_to_set" "$__cp" &&
458                                         return $SUCCESS
459                         fi
460                 else
461                         sysctl -n "dev.$__devname.$__devunit.%desc" \
462                                 2> /dev/null && return $SUCCESS
463                 fi
464         fi
465
466         local __dev __devtype __n=0
467         for __dev in $DEVICE_NAMES; do
468                 __n=$(( $__n + 1 ))
469                 debug= f_getvar _device_type$__n __devtype
470                 [ "${__type:-$__devtype}" = "$__devtype" ] || continue
471                 if [ "$__devtype" = "$DEVICE_TYPE_NETWORK" ]; then
472                         __devname=$( f_substr "$__name" 0 ${#__dev} )
473                         [ "$__devname" = "$__dev" ] || continue
474                 else
475                         __devname="${__name%%[0-9]*}"
476                         __devunit="${__name#$__devname}"
477                         __devunit="${__devunit%%[!0-9]*}"
478                         __devname=$( printf "$__dev" $__devunit )
479                         [ "$__devname" = "$__name" ] || continue
480                 fi
481                 debug= f_getvar _device_desc$__n $__var_to_set
482                 return $?
483         done
484
485         #
486         # Sensible fall-backs for specific types
487         #
488         case "$__type" in
489         $DEVICE_TYPE_CDROM)   __cp="<unknown cdrom device type>" ;;
490         $DEVICE_TYPE_DISK)    __cp="<unknown disk device type>" ;;
491         $DEVICE_TYPE_FLOPPY)  __cp="<unknown floppy device type>" ;;
492         $DEVICE_TYPE_USB)     __cp="<unknown usb storage device type>" ;;
493         $DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>" ;;
494         *)
495                 __cp="<unknown device type>"
496         esac
497
498         if [ "$__var_to_set" ]; then
499                 setvar "$__var_to_set" "$__cp"
500         else
501                 echo "$__cp"
502         fi
503
504         return $FAILURE
505 }
506
507 # f_device_rescan
508 #
509 # Rescan all devices, after closing previous set - convenience function.
510 #
511 f_device_rescan()
512 {
513         f_device_reset
514         f_device_get_all
515 }
516
517 # f_device_find $name [$type [$var_to_set]] 
518 #
519 # Find one or more registered devices by name, type, or both. Returns a space-
520 # separated list of devices matching the search criterion.
521 #
522 # If $var_to_set is missing or NULL, the device name(s) are printed to standard
523 # out for capturing in a sub-shell (which is less-recommended because of
524 # performance degredation; for example, when called in a loop).
525 #
526 f_device_find()
527 {
528         local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3"
529         local __dev __devname __devtype __found=
530         for __dev in $DEVICES; do
531                 device_$__dev get name __devname
532                 device_$__dev get type __devtype
533                 if [ "$__name" = "$__devname" -o ! "$__name" ] &&
534                    [ "$__type" = "$DEVICE_TYPE_ANY" -o \
535                      "$__type" = "$__devtype" ]
536                 then
537                         __found="$__found $__dev"
538                 fi
539         done
540         if [ "$__var_to_set" ]; then
541                 setvar "$__var_to_set" "${__found# }"
542         else
543                 echo $__found
544         fi
545         [ "$__found" ] # Return status
546 }
547
548 # f_device_init $name
549 #
550 # Initialize a device by evaluating its `init' function.
551 #
552 f_device_init()
553 {
554         local name="$1" init_func
555         device_$name get init init_func || return
556         ${init_func:-:} $name
557 }
558
559 # f_device_get $name $file [$probe]
560 #
561 # Read $file by evaluating the device's `get' function. The file is commonly
562 # produced on standard output (but it truly depends on the function called).
563 #
564 f_device_get()
565 {
566         local name="$1" file="$2" probe="$3" get_func
567         device_$name get get get_func || return
568         ${get_func:-:} $name "$file" ${3+"$probe"}
569 }
570
571 # f_device_shutdown $name
572 #
573 # Shutdown a device by evaluating its `shutdown' function.
574 #
575 f_device_shutdown()
576 {
577         local name="$1" shutdown_func
578         device_$name get shutdown shutdown_func || return
579         ${shutdown_func:-:} $name
580 }
581
582 # f_device_menu $title $prompt $hline $device_type [$helpfile]
583 #
584 # Display a menu listing all the devices of a certain type in the system.
585 #
586 f_device_menu()
587 {
588         f_dialog_title "$1"
589         local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
590         f_dialog_title_restore
591
592         local prompt="$2" hline="$3" type="$4" helpfile="$5"
593
594         local dev devtype devs=
595         for dev in $DEVICES; do
596                 device_$dev get type devtype || continue
597                 [ "$devtype" = "$type" ] || continue
598                 devs="$devs $dev"
599         done
600         [ "$devs" ] || return $FAILURE
601
602         local desc menu_list=
603         for dev in $devs; do
604                 device_$dev get desc desc
605                 f_shell_escape "$desc" desc
606                 menu_list="$menu_list '$dev' '$desc'"
607         done
608
609         local height width rows
610         eval f_dialog_menu_size height width rows \
611                                 \"\$title\"  \
612                                 \"\$btitle\" \
613                                 \"\$prompt\" \
614                                 \"\$hline\"  \
615                                 $menu_list
616
617         local errexit=
618         case $- in *e*) errexit=1; esac
619         set +e
620
621         local mtag
622         while :; do
623                 mtag=$( eval $DIALOG \
624                         --title \"\$title\"             \
625                         --backtitle \"\$btitle\"        \
626                         --ok-label \"\$msg_ok\"         \
627                         --cancel-label \"\$msg_cancel\" \
628                         ${helpfile:+                    \
629                           --help-button                 \
630                           --help-label \"\$msg_help\"   \
631                           ${USE_XDIALOG:+--help \"\"}   \
632                         }                               \
633                         --menu \"\$prompt\"             \
634                         $height $width $rows            \
635                         $menu_list                      \
636                         2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
637                 )
638                 local retval=$?
639
640                 [ $retval -ne 2 ] && break
641                         # Otherwise, the Help button was pressed
642                 f_show_help "$helpfile"
643                         # ...then loop back to menu
644         done
645         f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
646
647         [ "$errexit" ] && set -e
648
649         if [ $retval -eq 0 ]; then
650                 # Clean up the output of [X]dialog(1) and return it
651                 f_dialog_data_sanitize mtag
652                 echo "$mtag" >&2
653         fi
654
655         return $retval
656 }
657
658 #
659 # Short-hand
660 #
661 f_cdrom()   {  f_device_name_set $DEVICE_TYPE_CDROM   "$1" "$2" "$3";  }
662 f_disk()    {  f_device_name_set $DEVICE_TYPE_DISK    "$1" "$2" "$3";  }
663 f_floppy()  {  f_device_name_set $DEVICE_TYPE_FLOPPY  "$1" "$2" "$3";  }
664 f_serial()  {  f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2" "$3";  }
665 f_usb()     {  f_device_name_set $DEVICE_TYPE_USB     "$1" "$2" "$3";  }
666 f_network() {  f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2";       }
667
668 ############################################################ MAIN
669
670 # CDROM, Disk, Floppy, Serial, and USB devices/names
671 f_cdrom  "cd%d"   "SCSI CDROM drive"                  4
672 f_cdrom  "mcd%d"  "Mitsumi (old model) CDROM drive"   4
673 f_cdrom  "scd%d"  "Sony CDROM drive - CDU31/33A type" 4
674 f_disk   "aacd%d" "Adaptec FSA RAID array"            4
675 f_disk   "ada%d"  "ATA/SATA disk device"              16
676 f_disk   "amrd%d" "AMI MegaRAID drive"                4
677 f_disk   "da%d"   "SCSI disk device"                  16
678 f_disk   "idad%d" "Compaq RAID array"                 4
679 f_disk   "ipsd%d" "IBM ServeRAID RAID array"          4
680 f_disk   "mfid%d" "LSI MegaRAID SAS array"            4
681 f_disk   "mlxd%d" "Mylex RAID disk"                   4
682 f_disk   "twed%d" "3ware ATA RAID array"              4
683 f_floppy "fd%d"   "Floppy Drive unit A"               4
684 f_serial "cuau%d" "%s on device %s (COM%d)"           16
685 f_usb    "da%da"  "USB Mass Storage Device"           16
686
687 # Network interfaces/names
688 f_network "ae"    "Attansic/Atheros L2 Fast Ethernet"
689 f_network "age"   "Attansic/Atheros L1 Gigabit Ethernet"
690 f_network "alc"   "Atheros AR8131/AR8132 PCIe Ethernet"
691 f_network "ale"   "Atheros AR8121/AR8113/AR8114 PCIe Ethernet"
692 f_network "an"    "Aironet 4500/4800 802.11 wireless adapter"
693 f_network "ath"   "Atheros IEEE 802.11 wireless adapter"
694 f_network "aue"   "ADMtek USB Ethernet adapter"
695 f_network "axe"   "ASIX Electronics USB Ethernet adapter"
696 f_network "bce"   "Broadcom NetXtreme II Gigabit Ethernet card"
697 f_network "bfe"   "Broadcom BCM440x PCI Ethernet card"
698 f_network "bge"   "Broadcom BCM570x PCI Gigabit Ethernet card"
699 f_network "bm"    "Apple BMAC Built-in Ethernet"
700 f_network "bwn"   "Broadcom BCM43xx IEEE 802.11 wireless adapter"
701 f_network "cas"   "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"
702 f_network "cc3i"  "SDL HSSI sync serial PCI card"
703 f_network "cue"   "CATC USB Ethernet adapter"
704 f_network "cxgb"  "Chelsio T3 10Gb Ethernet card"
705 f_network "dc"    "DEC/Intel 21143 (and clones) PCI Fast Ethernet card"
706 f_network "de"    "DEC DE435 PCI NIC or other DC21040-AA based card"
707 f_network "disc"  "Software discard network interface"
708 f_network "ed"    "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"
709 f_network "el"    "3Com 3C501 Ethernet card"
710 f_network "em"    "Intel(R) PRO/1000 Ethernet card"
711 f_network "en"    "Efficient Networks ATM PCI card"
712 f_network "ep"    "3Com 3C509 Ethernet card/3C589 PCMCIA"
713 f_network "et"    "Agere ET1310 based PCI Express Gigabit Ethernet card"
714 f_network "ex"    "Intel EtherExpress Pro/10 Ethernet card"
715 f_network "fe"    "Fujitsu MB86960A/MB86965A Ethernet card"
716 f_network "fpa"   "DEC DEFPA PCI FDDI card"
717 f_network "fwe"   "FireWire Ethernet emulation"
718 f_network "fwip"  "IP over FireWire"
719 f_network "fxp"   "Intel EtherExpress Pro/100B PCI Fast Ethernet card"
720 f_network "gem"   "Apple GMAC or Sun ERI/GEM Ethernet adapter"
721 f_network "hme"   "Sun HME (Happy Meal Ethernet) Ethernet adapter"
722 f_network "ie"    "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"
723 f_network "igb"   "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"
724 f_network "ipw"   "Intel PRO/Wireless 2100 IEEE 802.11 adapter"
725 f_network "iwi"   "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"
726 f_network "iwn"   "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"
727 f_network "ixgbe" "Intel(R) PRO/10Gb Ethernet card"
728 f_network "ixgb"  "Intel(R) PRO/10Gb Ethernet card"
729 f_network "ix"    "Intel Etherexpress Ethernet card"
730         # Maintain sequential order of above(3): ixgbe ixgb ix
731 f_network "jme"   "JMicron JMC250 Gigabit/JMC260 Fast Ethernet"
732 f_network "kue"   "Kawasaki LSI USB Ethernet adapter"
733 f_network "le"    "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"
734 f_network "lge"   "Level 1 LXT1001 Gigabit Ethernet card"
735 f_network "lnc"   "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet"
736 f_network "lo"    "Loop-back (local) network interface"
737 f_network "lp"    "Parallel Port IP (PLIP) peer connection"
738 f_network "malo"  "Marvell Libertas 88W8335 802.11 wireless adapter"
739 f_network "msk"   "Marvell/SysKonnect Yukon II Gigabit Ethernet"
740 f_network "mxge"  "Myricom Myri10GE 10Gb Ethernet card"
741 f_network "nfe"   "NVIDIA nForce MCP Ethernet"
742 f_network "nge"   "NatSemi PCI Gigabit Ethernet card"
743 f_network "ng"    "Vimage netgraph(4) bridged Ethernet device"
744         # Maintain sequential order of above(2): nge ng
745 f_network "nve"   "NVIDIA nForce MCP Ethernet"
746 f_network "nxge"  "Neterion Xframe 10GbE Server/Storage adapter"
747 f_network "pcn"   "AMD Am79c79x PCI Ethernet card"
748 f_network "plip"  "Parallel Port IP (PLIP) peer connection"
749 f_network "ral"   "Ralink Technology IEEE 802.11 wireless adapter"
750 f_network "ray"   "Raytheon Raylink 802.11 wireless adapter"
751 f_network "re"    "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter"
752 f_network "rl"    "RealTek 8129/8139 PCI Ethernet card"
753 f_network "rue"   "RealTek USB Ethernet card"
754 f_network "rum"   "Ralink Technology USB IEEE 802.11 wireless adapter"
755 f_network "sf"    "Adaptec AIC-6915 PCI Ethernet card"
756 f_network "sge"   "Silicon Integrated Systems SiS190/191 Ethernet"
757 f_network "sis"   "SiS 900/SiS 7016 PCI Ethernet card"
758 f_network "sk"    "SysKonnect PCI Gigabit Ethernet card"
759 f_network "snc"   "SONIC Ethernet card"
760 f_network "sn"    "SMC/Megahertz Ethernet card"
761         # Maintain sequential order of above(2): snc sn
762 f_network "sr"    "SDL T1/E1 sync serial PCI card"
763 f_network "ste"   "Sundance ST201 PCI Ethernet card"
764 f_network "stge"  "Sundance/Tamarack TC9021 Gigabit Ethernet"
765 f_network "ti"    "Alteon Networks PCI Gigabit Ethernet card"
766 f_network "tl"    "Texas Instruments ThunderLAN PCI Ethernet card"
767 f_network "txp"   "3Com 3cR990 Ethernet card"
768 f_network "tx"    "SMC 9432TX Ethernet card"
769         # Maintain sequential order of above(2): txp tx
770 f_network "uath"  "Atheros AR5005UG and AR5005UX USB wireless adapter"
771 f_network "upgt"  "Conexant/Intersil PrismGT USB wireless adapter"
772 f_network "ural"  "Ralink Technology RT2500USB 802.11 wireless adapter"
773 f_network "urtw"  "Realtek 8187L USB wireless adapter"
774 f_network "vge"   "VIA VT612x PCI Gigabit Ethernet card"
775 f_network "vlan"  "IEEE 802.1Q VLAN network interface"
776 f_network "vr"    "VIA VT3043/VT86C100A Rhine PCI Ethernet card"
777 f_network "vx"    "3COM 3c590 / 3c595 Ethernet card"
778 f_network "wb"    "Winbond W89C840F PCI Ethernet card"
779 f_network "wi"    "Lucent WaveLAN/IEEE 802.11 wireless adapter"
780 f_network "wpi"   "Intel 3945ABG IEEE 802.11 wireless adapter"
781 f_network "wx"    "Intel Gigabit Ethernet (82452) card"
782 f_network "xe"    "Xircom/Intel EtherExpress Pro100/16 Ethernet card"
783 f_network "xl"    "3COM 3c90x / 3c90xB PCI Ethernet card"
784 f_network "zyd"   "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"
785
786 f_dprintf "%s: Initialized %u known device names/descriptions." device.subr \
787           "$( set -- $DEVICE_NAMES; echo $# )"
788
789 #
790 # Scan for the above devices unless requeted otherwise
791 #
792 f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL"
793 case "$DEVICE_SELF_SCAN_ALL" in
794 ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
795 *) f_device_get_all
796 esac
797
798 f_dprintf "%s: Successfully loaded." device.subr
799
800 fi # ! $_DEVICE_SUBR