4 # utility to manipulate system configuration information help
5 # in a RedBoot SysConf partition
7 # load the utility functions (unless this is being called just
8 # to load these functions!)
9 test "$1" != sysconf
&& .
/etc
/default
/functions
11 # NSLU2 flash layout is non-standard.
20 ffspart
="filesystem";;
24 # return true if the SysConf partition exists and seems to be
25 # potentially valid (it starts with a reasonable length).
28 sysdev
="$(mtblockdev $syspart)"
29 test -n "$sysdev" -a -b "$sysdev" &&
30 devio
"<<$sysdev" '!! b.10>s32768<&!'
34 # sysconf_read [prefix]
35 # read the $syspart partition (if present) writing the result into
36 # /etc/default/sysconf, if the result is empty it will be removed.
38 local sysdev sedcmd mac config_root
40 rm -f /tmp
/sysconf.new
41 sysdev
="$(mtblockdev $syspart)"
44 # Read the defined part of $syspart into /etc/default/sysconf.
45 # $syspart has lines of two forms:
50 # In practice $syspart also contains other stuff, use the command:
52 # devio '<</dev/mtd1;cpb'
54 # to examine the current settings. The badly formatted stuff
55 # is removed (to be exact, the sed script selects only lines
56 # which match one of the two above). The lan interface, which
57 # on NSLU2 defaults to ixp0, is changed to the correct value for
58 # slugos, eth0. The bootproto, which LinkSys sets to static in
59 # manufacturing, is reset to dhcp if the IP is still the
60 # original (192.168.1.77)
61 sedcmd
='/^\[[^][]*\]$/p;'
62 # only do the ip_addr and lan_interface fixups on NSLU2
63 if test "$(machine)" = nslu2
66 s/^lan_interface=ixp0$/lan_interface=eth0/;
67 /^ip_addr=192\.168\.1\.77$/,/^bootproto/s/^bootproto=static$/bootproto=dhcp/;'
69 # always fix up the hardware addr if it is present
74 s/^hw_addr=.*$/hw_addr='"$mac"'/;'
76 # and only print lines of the correct form
78 /^[-a-zA-Z0-9_][-a-zA-Z0-9_]*=/p'
80 devio
"<<$sysdev" cpb fb1
,10 |
sed -n "$sedcmd" >/tmp
/sysconf.new
83 # test the result - sysconf must be non-empty
84 if test -s /tmp
/sysconf.new
86 mv /tmp
/sysconf.new
"$config_root/etc/default/sysconf"
88 rm -f /tmp
/sysconf.new
94 # sysconf_default [prefix]
95 # Provde a default /etc/default/sysconf when there is no $syspart partition,
96 # or when it is invalid, this function will read from an existing sysconf,
97 # copying the values into the new one.
98 # sysconf_line tag config-tag
99 # write an appropriate line if the config value is non-empty
104 test -n "$value" && echo "$1"="$value"
112 sysconf_line hw_addr mac
113 sysconf_line disk_server_name
host
114 sysconf_line w_d_name domain
115 sysconf_line lan_interface iface
116 sysconf_line ip_addr ip
117 sysconf_line netmask netmask
118 sysconf_line gateway gateway
119 sysconf_line dns_server1 dns
120 sysconf_line dns_server2 dns2
121 sysconf_line dns_server3 dns3
122 sysconf_line bootproto boot
124 mv /tmp
/sysconf.new
"$config_root/etc/default/sysconf"
128 # sysconf_reload [prefix]
129 # read the values from /etc/default/sysconf and use these values to set
130 # up the following system files:
135 # /etc/network/interfaces
139 local config_root
host domain iface boot ip netmask gateway ifname iftype
141 host="$(config host)"
142 test -n "$host" && echo "$host" >"$config_root/etc/hostname"
143 domain
="$(config domain)"
144 test -n "$domain" && echo "$domain" >"$config_root/etc/defaultdomain"
146 # The DNS server information gives up to three nameservers,
147 # but this currently only binds in the first.
149 test -n "$domain" && echo "search $domain"
150 test -n "$(config dns)" && echo "nameserver $(config dns)"
151 test -n "$(config dns2)" && echo "nameserver $(config dns2)"
152 test -n "$(config dns3)" && echo "nameserver $(config dns3)"
153 } >"$config_root/etc/resolv.conf"
155 # Ethernet information. This goes into /etc/network/interfaces,
156 # however this is only used for static setup (and this is not
157 # the default). With dhcp the slugos udhcp script,
158 # /etc/udhcpc.d/50default, loads the values from sysconf.
159 iface
="$(config iface)"
160 boot
="$(config boot)"
161 # Only dhcp and static are supported at present - bootp
162 # support requires installation of appropriate packages
163 # dhcp is the fail-safe
170 netmask
="$(config netmask)"
171 gateway
="$(config gateway)"
173 echo "# /etc/network/interfaces"
174 echo "# configuration file for ifup(8), ifdown(8)"
176 echo "# The loopback interface"
178 echo "iface lo inet loopback"
180 echo "# The interface used by default during boot"
182 echo "# Automatically generated from /etc/default/sysconf"
183 echo "# address, netmask and gateway are ignored for 'dhcp'"
184 echo "# but required for 'static'"
185 echo "iface $iface inet $boot"
186 # The following are ignored for DHCP but are harmless
187 test -n "$ip" && echo " address $ip"
188 test -n "$netmask" && echo " netmask $netmask"
189 test -n "$gateway" && echo " gateway $gateway"
191 # Now read all the other ARPHRD_ETHER (type=1) interfaces
192 # and add an entry for each.
193 for ifname
in $
(test -d /sys
/class
/net
&& ls /sys
/class
/net
)
195 if test -r "/sys/class/net/$ifname/type" -a "$ifname" != "$iface"
197 read iftype
<"/sys/class/net/$ifname/type"
200 echo "# /sys/class/net/$ifname:"
202 echo "iface $ifname inet dhcp";;
206 } >"$config_root/etc/network/interfaces"
208 # Finally rewrite /etc/motd
209 { echo "Host name: $host"
210 echo "Domain name: $domain"
211 echo "Host MAC: $(config mac)"
212 echo "Network boot method: $boot"
214 static
) echo "Host IP address: $ip";;
216 echo "Use 'turnup init' to reset the configuration"
217 echo "Use 'turnup preserve' to save the configuration permanently"
218 echo "Use 'turnup restore' to restore a previously saved configuration"
219 echo "Use 'turnup disk|nfs -i <device> options to initialise a non-flash root"
220 echo "Use 'turnup help' for more information"
221 } >"$config_root/etc/motd"
225 # sysconf_save_conffiles <flash-directory> <dest> <list>
226 # preserve the configuration files in a directory or in a CPIO archive
227 # (which is *not* compressed). If <dest> is a directory the files are
228 # copied, otherwise a CPIO archive is made with that name. <list> is
229 # the listing file giving the preserved files and the processing option.
230 sysconf_save_conffiles
(){
231 local ffsdir dest list
file
235 test -n "$ffsdir" -a -r "$ffsdir/etc/default/conffiles" -a -n "$saved" -a -n "$list" ||
{
236 echo "sysconf_save_conffiles: invalid arguments: '$*'" >&2
237 echo " usage sysconf_save_conffiles <flash-directory> <dest> <list>" >&2
242 find etc
/*.conf $
(sed 's!^/!!' usr
/lib
/ipkg
/info
/*.conffiles
) ! -type d
-newer etc
/.configured
-print |
244 exec sed 's/#.*$//;/^[ ]*$/d' etc
/default
/conffiles
246 awk '{ op=$1; $1=""; file[$0]=op }
247 END{ for (f in file) if (file[f] != "ignore") print file[f] f }' |
250 if test -e "$ffsdir/$file"
259 exec cpio -p -d -m -u "$saved"
261 exec cpio -o -H crc
>"$saved"
267 # sysconf_verify file
268 # this is called with the name of a 'diff' file which is, indeed,
269 # different and with all the std streams connected to the tty. It
270 # returns a status code to say whether (0) or not (1) to copy the
273 # globals: the following must be defined in the calling context!
274 # saved: the directory containing the unpacked saved files
275 # ffsdir: the flash directory to which the files are being restored (/)
277 sysconf_verify_help
() {
278 echo "Please specify how to handle this file or link, the options are as follows,"
279 echo "two character abbreviations may be used:"
281 echo " keep: retain the old file, overwrite the new flash image file"
282 echo " upgrade: retain the new file, the old (saved) file is not used"
283 echo " diff: display the differences between the old and the new using diff -u"
284 echo " shell: temporarily start an interactive shell (sh -i), exit to continue"
285 echo " skip: ignore this file for the moment. The file is left in the directory"
286 echo " $saved and many be handled after this script has completed"
292 # return 1 here causes the file not to be overwritten,
293 # control should never get here!
294 test -n "$sysconf_noninteractive" && {
295 echo "$0: $*: changed file cannot be handled non-interactively" >&2
300 echo "$0: $file: configuration file changed."
301 sysconf_verify_help
"$file"
308 up
*) rm "$saved/$file"
310 di
*) echo "DIFF OLD($saved) NEW($ffsdir)"
311 diff -u "$saved/$file" "$ffsdir/$file";;
312 sh
*) PS1
="$file: " sh
-i;;
314 *) sysconf_verify_help
"$file";;
318 # the same, but for a link
319 sysconf_verify_link
() {
322 # return 1 here causes the file not to be overwritten,
323 # control should never get here!
324 test -n "$sysconf_noninteractive" && {
325 echo "$0: $*: changed link cannot be handled non-interactively" >&2
330 echo "reflash: $link: configuration link changed."
331 sysconf_verify_help
"$link"
338 up
*) rm "$saved/$link"
341 echo "OLD($saved): $link -> $(readlink "$saved/$link")"
342 echo "NEW($ffsdir): $link -> $(readlink "$ffsdir/$link")";;
343 sh
*) PS1
="$link: " sh
-i;;
345 *) sysconf_verify_help
"$link";;
351 # sysconf_restore_conffiles <flash-directory> <source-dir> <restore>
352 # restore the configuration files from a directory. 'source-dir'
353 # If <source> is a directory of files from sysconf_save_conffiles. The
354 # list of files restored is written to the third argument (restore),
355 # but is not required (/dev/null would be ok).
357 # the list of files to restore is read from stdin, along with the
358 # processing option for each file (the format is as produced by
359 # sysconf_save_conffiles in the 'list' output).
360 sysconf_restore_conffiles
(){
361 local ffsdir saved restore
362 # these are the globals used by the above function
366 test -n "$ffsdir" -a -r "$ffsdir/etc/default/conffiles" -a -d "$saved" -a -n "$restore" ||
{
367 echo "restore_conffiles: invalid arguments: '$*'" >&2
368 echo " usage sysconf_restore_conffiles <flash-directory> <source-dir> <list>" >&2
372 # read the list and process each given file
375 # handle .configured specially (to preserve the original datestamp)
376 if test "$file" = "etc/.configured"
378 # this should definately not fail because of the test above!
379 if cp -a "$saved/$file" "$ffsdir/$file"
383 echo "sysconf_restore_conffiles: $file: timestamp copy failed (ignored)" >&2
385 elif test -h "$saved/file" -o -h "$ffsdir/$file"
387 # new or old symbolic link
388 if test -h "$saved/$file" -a -h "$ffsdir/$file" &&
389 test "$(readlink "$saved/$file")" = "$(readlink "$ffsdir/$file")"
394 # assume a change regardless
399 diff) # need user input
400 if sysconf_verify_link
"$file" <>/dev
/tty
>&0 2>&0
408 # only overwrite if necessary
409 if test -e "$ffsdir/$file" && cmp -s "$saved/$file" "$ffsdir/$file"
413 elif test ! -e "$ffsdir/$file"
423 diff) # the files are different, get user input
424 if sysconf_verify
"$file" <>/dev
/tty
>&0 2>&0
432 done 3>"$restore" |
(cd "$saved"; exec cpio -p -d -u "$ffsdir")
436 # sysconf_test_restore <flash-directory> <source-dir>
437 # return true only if the restore does not need to do an interactive
439 sysconf_test_restore
(){
441 # these are the globals used by the above function
444 # this is an error case, but return 0 so that the error is
446 test -n "$ffsdir" -a -r "$ffsdir/etc/default/conffiles" -a -d "$saved" ||
449 # read the list and check each diff file (this is just a copy of the
450 # logic above with all the work removed!)
453 # handle .configured specially (to preserve the original datestamp)
454 if test "$op" != diff
457 elif test "$file" = "etc/.configured"
460 elif test -h "$saved/file" -o -h "$ffsdir/$file"
462 # new or old symbolic link
463 if test -h "$saved/$file" -a -h "$ffsdir/$file" &&
464 test "$(readlink "$saved/$file")" = "$(readlink "$ffsdir/$file")"
468 # assume a change regardless
472 # only overwrite if necessary
473 if test -e "$ffsdir/$file" && cmp -s "$saved/$file" "$ffsdir/$file"
476 elif test ! -e "$ffsdir/$file"
491 # save the system configuration to $syspart - $syspart must exist and
492 # there must be a writeable device for it.
494 local sysdev ffsdev ffsdir saved list size status
495 ffsdev
="$(mtblockdev $ffspart)"
496 sysdev
="$(mtblockdev $syspart)"
498 if test -n "$sysdev" -a -b "$sysdev" -a -n "$ffsdev" -a -b "$ffsdev"
500 # this will succeed silently if the flash device is on /
501 umountflash
"$ffsdev" ||
exit 1
503 # Everything is umounted, now remount on a temporary directory.
504 ffsdir
="/tmp/flashdisk.$$"
506 echo "$0: $ffsdir: failed to create temporary directory" >&2
510 mountflash
"$ffsdev" "$ffsdir" -o ro ||
{
514 # need temporary files for the cpio output and the listing
516 list
=/tmp
/preserve.$$
517 rm -rf "$saved" "$list"
518 sysconf_save_conffiles
"$ffsdir" "$saved" "$list" ||
{
519 echo "$0: $saved: archive of saved configuration files failed" >&2
522 umount
"$ffsdir" && rmdir "$ffsdir" ||
523 echo "$0: $ffsdir: temporary directory cleanup failed" >&2
526 # ignore the error in this case:
527 umount
"$ffsdir" && rmdir "$ffsdir" ||
528 echo "$0: $ffsdir: temporary directory cleanup failed" >&2
531 # /etc/default/sysconf the basic config
532 # /tmp/preserve.$$ the list of saved files
533 # /tmp/cpio.$$ the CPIO archive of those files
535 # make one big file with the sysconf data followed by the
536 # compressed archive in /tmp/sysconf.$$
537 { { cat /etc
/default
/sysconf
539 } |
sed -n '1,/^\[preserve\]^/p'
545 size
="$(devio "<</tmp
/sysconf.$$
" 'pr$')"
546 gzip -9 <"$saved" >>/tmp
/sysconf.$$
548 # more cleanup, then try to write the new sysconf to $syspart
549 # the format is a 4 byte big-endian length then the text data
550 # if the data won't fit exit with error code 7
552 devio
-p "<</tmp/sysconf.$$" ">>$sysdev" '
561 1) echo " failed" >&2
562 echo " $syspart could not be written (no changes made)" >&2;;
563 3) echo " failed" >&2
564 echo " $syspart partially written, you may want to reset it" >&2;;
565 7) echo " failed" >&2
566 echo " $syspart is too small: $size bytes required" >&2
567 echo " No change made" >&2;;
568 *) echo " failed" >&2
569 echo " Internal error writing $syspart" >&2;;
572 rm -f /tmp
/sysconf.$$
574 echo "sysconf save: $syspart or $ffspart partition not found" >&2
575 echo " A RedBoot partition named '$syspart' must exist in the system" >&2
576 echo " flash memory for this command to work, and there must be a" >&2
577 echo " block device to access this partition (udev will normally" >&2
578 echo " create this automatically. The flash partition contents must" >&2
579 echo " also be accessible in a partition called '$ffspart'" >&2
581 echo " To create the $syspart partition use the 'fis create' command" >&2
582 echo " in the RedBoot boot loader, it is sufficient to make the" >&2
583 echo " partition one erase block in size unless you have substantially" >&2
584 echo " increased the size of the files listed in /etc/default/conffiles" >&2
591 # sysconf_restore [auto]
592 # restore previously saved configuration information from $syspart
593 sysconf_restore_error
(){
597 # -------------------------------------------------------------------------------
598 { echo " WARNING: saved configuration files not restored"
599 test -n "$1" && echo "$*"
601 echo "The configuration of this machine has been reinitialised using the values"
602 echo "from /etc/default/sysconf, however configuration files saved in the $syspart"
603 echo "partition have not been restored."
605 echo "You can restore these files by correcting any reported errors then running"
607 echo " sysconf restore"
609 echo "from the command line. This will completely reinitialise the configuration"
610 echo "using the information in the $syspart partition."
612 cat "$root/etc/motd" >&2
616 local sysdev ffsdev ffsdir saved restore size status sysconf_noninteractive config_root
618 # if set this means 'do no diff' - this avoids the code above which
619 # would open /dev/tty and therefore allows this stuff to be done from
621 sysconf_noninteractive
=
622 test "$1" = auto
&& sysconf_noninteractive
=1
624 ffsdev
="$(mtblockdev $ffspart)"
625 sysdev
="$(mtblockdev $syspart)"
627 if test -n "$sysdev" -a -b "$sysdev" -a -n "$ffsdev" -a -b "$ffsdev" &&
630 # this will succeed silently if the flash device is on /
631 umountflash
"$ffsdev" ||
exit 1
633 # Everything is umounted, now remount on a temporary directory.
634 ffsdir
="/tmp/flashdisk.$$"
635 config_root
="$ffsdir"
637 echo "$0: $ffsdir: failed to create temporary directory" >&2
641 mountflash
"$ffsdev" "$ffsdir" ||
{
646 # first restore the $syspart section
647 sysconf_read
"$ffsdir" || sysconf_default
"$ffsdir"
649 # now use this to regenerate the system files
650 sysconf_reload
"$ffsdir"
652 # now examine the [preserve] section, if it is there restore
654 if test -n "$(syssection preserve)"
656 # 'saved' is a directory, 'restore' is a file (which is
657 # used to detect unrestored files). The directory needs
658 # to be populated with files.
660 restore
=/tmp
/restore.$$
661 rm -rf "$saved" "$restore"
664 sysconf_restore_error
"$ffsdir" "$saved: failed to create temporary directory"
668 # the CPIO archive is gzip compressed after the text part
669 # of sysconf, gzip will handle the LZ stream termination
670 # correctly (and break the pipe) so we don't need to know
671 # the real length of the data
672 devio
"<<$sysdev" '<=b4+.' 'cp $s-' | gunzip |
(
674 exec cpio -i -d -m -u
677 sysconf_restore_error
"$ffsdir" "$saved: cpio -i failed"
680 # either there must be no 'diff' files or it must
681 # be possible to interact with a real user.
682 if test -z "$sysconf_noninteractive" ||
683 syssection preserve | sysconf_test_restore
"$ffsdir" "$saved"
686 # remove the 'init' motd from sysconf_reload
687 rm "$ffsdir/etc/motd"
689 # now restore from the directory, using the information in
690 # the preserve section, if this fails in a non-interactive
691 # setting the system might not reboot
692 syssection preserve |
693 sysconf_restore_conffiles
"$ffsdir" "$saved" "$restore" ||
{
694 # there is a chance of the user cleaning this up
695 #------------------------------------------------------------------------------
696 sysconf_restore_error
"$ffsdir" \
697 "$0: $saved: restore of saved configuration files failed.
698 The flash file system is mounted on $ffsdir.
699 The saved files are in $saved and the list of files selected for
700 restore is in $restore.
701 You should restore any required configuration from $saved, then umount
703 # this prevents cleanup/umount
707 # remove the copied files (i.e. the ones which were preserved)
709 exec rm $
(cat "$restore")
713 # clean up, files left in $saved need to be handled by the user
714 files
="$(find "$saved" ! -type d -print)"
717 #------------------------------------------------------------------------------
718 sysconf_restore_error
"$ffsdir" \
719 "$0: some saved configuration files have not been handled:
723 These files can be examined in $saved and restored to
724 $ffsdir if required. The saved files are in a temporary
725 directory and will not be retained across a reboot - copy then elsewhere if
726 you are unsure whether they are needed."
730 # so this is safe now (no files, links etc)
734 # non-interactive and some changed diff files
735 sysconf_restore_error
"$ffsdir" \
736 "$0: some of the saved configuration files must be
737 examined before restoration"
738 # but continue to the umount
742 # ignore the error in this case:
743 umount
"$ffsdir" && rmdir "$ffsdir" ||
744 echo "$0: $ffsdir: temporary directory cleanup failed" >&2
747 echo "sysconf restore: $syspart or $ffspart partition not found" >&2
748 echo " You must have used 'sysconf save' to save configuration data" >&2
749 echo " into the $syspart partition before using this command. The command" >&2
750 echo " will restore the configuration data to the flash root partition" >&2
751 echo " named '$ffspart' - this must also be accessible." >&2
761 # -------------------------------------------------------------------------------
762 echo "sysconf: usage: sysconf read|default|reload|save|restore" >&2
763 echo " read: the current $syspart partition is read into /etc/default/sysconf" >&2
764 echo " default: a default /etc/default/sysconf is created" >&2
765 echo " reload: system configuration files are recreated from /etc/default/sysconf" >&2
766 echo " save: /etc/default/sysconf and the files listed in /etc/default/conffiles" >&2
767 echo " are written to the $syspart partition" >&2
768 echo " restore: the configuration information in the $syspart partition saved by" >&2
769 echo " 'sysconf save' is restored" >&2
774 #if [ "$(machine)" = "storcenter" ]; then
775 # echo "sysconf not (yet) supported on storcenter"
779 test $# -gt 0 && shift
780 case "$sysconf_command" in
781 read) sysconf_read
"$@";;
782 default
)sysconf_default
"$@";;
783 reload
) sysconf_reload
"$@";;
784 save
) sysconf_save
"$@";;
785 restore
)sysconf_restore
"$@";;
786 valid
) sysconf_valid
"$@";;
788 sysconf
)# just load the functions