From owner-freebsd-mobile Mon Oct 27 18:12:18 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id SAA15958 for mobile-outgoing; Mon, 27 Oct 1997 18:12:18 -0800 (PST) (envelope-from owner-freebsd-mobile) Received: from word.smith.net.au (vh1.gsoft.com.au [203.38.152.122]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id SAA15952 for ; Mon, 27 Oct 1997 18:12:06 -0800 (PST) (envelope-from mike@word.smith.net.au) Received: from word.smith.net.au (localhost.gsoft.com.au [127.0.0.1]) by word.smith.net.au (8.8.7/8.8.5) with ESMTP id MAA00954; Tue, 28 Oct 1997 12:37:01 +1030 (CST) Message-Id: <199710280207.MAA00954@word.smith.net.au> X-Mailer: exmh version 2.0zeta 7/24/97 To: davet@ttfn.com cc: Warner Losh , freebsd-mobile@FreeBSD.ORG Subject: Re: How do you solve... In-reply-to: Your message of "Mon, 27 Oct 1997 14:52:09 -0800." <13903.877992729@nomad> Mime-Version: 1.0 Content-Type: multipart/mixed ; boundary="==_Exmh_21172141880" Date: Tue, 28 Oct 1997 12:37:00 +1030 From: Mike Smith Sender: owner-freebsd-mobile@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk This is a multipart MIME message. --==_Exmh_21172141880 Content-Type: text/plain; charset=us-ascii > ------- =_aaaaaaaaaa0 > Content-Type: text/plain; charset="us-ascii" > Content-ID: <13900.877992729.1@nomad> > Content-MD5: TG/OeIqtvEKKsx94a+5wqw== > Content-Transfer-Encoding: quoted-printable Please avoid using 'quoted-unprintable' for plain message text. Replying to it is a Real Pain. > My laptop's been using the ISC DHCP client for the past 8 months to > configureitself for both my home and work networks. It works great, > and saves me the hassle of remembering to reconfigure anything by hand. > The only problems I've had to hack around are getting sendmail to > recognize the change to resolv.conf so it can talk to the local > nameserver, and changing the mailrelay so it can route mail out > past my home firewall. (Elegant idea for handling such dynamic > configuration issues are always welcome.) Rewrite your /etc/sendmail.cf and change the O FallbackMXhost= line to point to your local firewall when you're there, and then 'killall -HUP sendmail'. It'll reread your config at that point; I'm not sure if it actually restarts proper, which is what it would take to get it to pick up changes to /etc/resolv.conf. I actually use a fairly neat tool I wrote called 'personality' for managing this (attached). Just add '/sbin/personality menu' in /etc/rc just before rc.conf is read; I use: # If the system personality system is configured, run the selector if [ -d /etc/personality ]; then /sbin/personality menu 5 fi mike --==_Exmh_21172141880 Content-Type: text/plain; name="personality"; charset=us-ascii Content-Description: personality Content-Disposition: attachment; filename="personality" #!/bin/sh ############################################################################## # # Copyright (c) 1997 Michael Smith # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $Id$ # ############################################################################## # # This script provides functionality for manipulating collections of # configuration files which can be organised so as to alter the # personality of a system. # # Initially, the "base" personality is established. This personality # contains the "reference" copies of configuration files, and is used # when creating new personalities. The files which are currently # considered part of the system's personality are those contained in # the base personality. # # A new personality is established by making a copy of the base # personality under a new name. Each personality maintains a # separate copy of all configuration files under /etc/personality. # # To install a new personality, the files currently in place are # saved back to the current personality as indicated in # /etc/personality/current, and the files for the new personality # copied into place. The 'select' and 'menu' commands which perform # these installations are implemented in such a fashion as to only # require the tools available on the root filesystem, so that they # may be invoked at the earliest stage during system startup. # # If the current personality has become damaged, it can be restored # from the saved copy. # # Files can be added to and removed from the personality set. When # a new file is added, it is copied from the current system into all # personalities and added to the list file. When a file is removed # the current version is kept in place, but all copies are removed # from saved personalities and the file is removed from the list. # # XXX To Do : # Files can be inherited by one personality from another. This is # simply achieved by copying the relevant files under /etc/personality, # and into the current system if required. # ############################################################################## # Establish some global constants P_ROOT=/etc/personality #P_ROOT=/tmp/personality P_BASE="${P_ROOT}/_base" P_CURRENT="${P_ROOT}/current" P_FILES="${P_ROOT}/files" P_LIST="${P_ROOT}/list" scriptname="$0" ############################################################################## # pers_main # # Execution begins here after the file has been read. # pers_main() { case "$1" in menu) pers_menu $2 $3 ;; select) pers_select $2 ;; restore) pers_restore ;; save) pers_save ;; saveas) pers_saveas $2 pers_reindex ;; create) pers_create $2 pers_reindex ;; delete) pers_delete $2 pers_reindex ;; add) pers_add $2 pers_reindex ;; list) pers_list ;; remove) pers_remove $2 pers_reindex ;; init) pers_init pers_reindex ;; *) usage ;; esac } ############################################################################## # pers_menu # # Present a menu of currently-selectable personalities, assign hotkeys, # describe the default and optionally go with the default after a timeout # pers_menu() { # Look and see if there's actually anything to work with if [ ! -d "${P_ROOT}" ]; then return fi # Pick up a timeout if specified, default to 10 seconds timeout=10 if [ ! -z "$1" ]; then timeout="$1" fi # Assign a default, if suitable defpers="" defname="" if [ -f "${P_CURRENT}" ]; then defpers=`cat "${P_CURRENT}"` defname="${defpers}" fi # Loop prompting/reading input until we get a result while :; do # Print menu echo ""; echo "Select System Personality" echo "=========================" hkey=0 for pers in `cat "${P_LIST}"`; do echo " ${hkey}) ${pers}" eval index_${hkey}="${pers}" hkey=`expr ${hkey} + 1` done echo ""; echo " Default : ${defname}" read -t "${timeout}" -p " Selection : " input eval selvar=\$index_"${input}" selpers="" if [ -z "${input}" ]; then selpers="${defpers}" break elif [ -n "${selvar}" ]; then selpers="${selvar}" break elif [ -d "${P_ROOT}/_${input}" ]; then selpers="${input}" break fi done # $selpers now contains the personality we wish to select, # or is empty if we selected the default when there was none if [ -z "${selpers}" ]; then return fi # select the personality nominated pers_select "${selpers}" } ############################################################################## # pers_select # # Copy the files from the nominated personality out of the repository # into the real system. Note that this must be able to run with # nothing other than the contents of /bin available. # pers_select() { src="${P_ROOT}/_$1"; if [ ! -d "${src}" ]; then fail "no such personality '$1'" fi # Iterate over the file listing, copy them all out for file in `cat "${P_FILES}"`; do cp -p "${src}/${file}" "${file}" done # Register this personality as being current echo "$1" > "${P_CURRENT}" } ############################################################################## # pers_restore # # Reload the configuration files for the current personality, eliminating # any changes that may have been made. # pers_restore() { if [ ! -e "${P_CURRENT}" ]; then fail "no personality currently active" fi # Check that the current personality exists pers=`cat "${P_CURRENT}"` src="${P_ROOT}/_${pers}" if [ ! -d "${src}" ]; then fail "current personality '${pers}' not in the repository!" fi # Iterate over the file listing, copy them all out for file in `cat "${P_FILES}"`; do cp -p "${src}/${file}" "${file}" done } ############################################################################## # pers_save # # If a personality is current, save the current set of files to that # personality. # pers_save() { if [ ! -e "${P_CURRENT}" ]; then fail "no personality currently active" fi # Check that the current personality exists pers=`cat "${P_CURRENT}"` dest="${P_ROOT}/_${pers}" if [ ! -d "${dest}" ]; then fail "current personality '${pers}' not in the repository!" fi # OK, go ahead and save stuff. If this fails, we're # moderately stuffed, so don't worry about it. for file in `cat "${P_FILES}"`; do stub=`dirname "${file}"` mkdir -p "${dest}/${stub}" cp -p "${file}" "${dest}/${file}" done } ############################################################################## # pers_saveas # # Take the currently-active set of configuration files, and save them as # a new personality, set the new personality as current. # pers_saveas() { dest="${P_ROOT}/_$1" if [ -e "${dest}" ]; then fail "cannot create new personality '$1', name already in use" fi # Create the personality directory mkdir -p "${dest}" || pers_saveas_fail "$1" # iterate over files to save, copy them in for file in `cat "${P_FILES}"`; do stub=`dirname "${file}"` mkdir -p "${dest}/${stub}" cp -p "${file}" "${dest}/${file}" || pers_saveas_fail $1 done # new personality is current echo "$1" > "${P_CURRENT}" } ######################################## # pers_saveas_fail # # The 'save as' operation failed. Clean # up and emit a failure message. # pers_saveas_fail() { rm -Rf "${P_ROOT}/_$1" fail "could not save current personality as '$1'" } ############################################################################## # pers_create # # Create a new personality, duplicated from the current base personality # pers_create() { if [ -e "${P_ROOT}/_$1" ]; then fail "cannot create new personality '$1', name already in use" fi # Ok, duplicate it cp -Rp "${P_BASE}" "${P_ROOT}/_$1" || pers_create_fail "$1" } ######################################## # pers_create_fail # # An attempt to create a personality failed. # Clean up and exit with an error message. # pers_create_fail() { rm -Rf "${P_ROOT}/_$1" fail "'$1' could not be created" } ############################################################################## # pers_delete # # Remove a personality from the system. It is legitimate to remove # the current personality. # pers_delete() { if [ ! -e "${P_ROOT}/_$1" ]; then fail "no such personality '$1' to remove" fi if [ "$1" = _base ]; then fail "cannot remove base personality" fi # If the requested personality is current, remove the # reference. if [ -e "${P_CURRENT}" ]; then if [ `cat "${P_CURRENT}"` = "$1" ]; then rm -f "${P_CURRENT}" fi fi # Remove the repository entry rm -Rf "${P_ROOT}/_$1"; # Make sure it's gone if [ -e "${P_ROOT}/_$1" ]; then fail "failed to completely remove personality '$1'"; fi } ############################################################################## # pers_add # # Add a new file to the system; copy it from the 'real' path into # each personality directory. Check first to make sure it's not already # part of the system, and check that the path supplied is absolute. # # The file is stored with its full path relative to the repository # directory. # pers_add() { if [ ! -r "/$1" ]; then fail "cannot read '$1' to add to the Personality System" fi if [ -e "${P_BASE}/$1" ]; then fail "file '$1' already part of the Personality System" fi if [ ! -f "$1" ]; then fail "only files can be added to the Personality System" fi # looks OK, copy it in stub=`dirname "$1"` for targ in ${P_ROOT}/_*; do mkdir -p "${targ}/${stub}" cp -p "$1" "${targ}/${stub}" || pers_add_fail "$1"; done } ######################################## # pers_add_fail # # A failure occurred while adding a file to # the repository; back out any copies that # made it in and abort with an error. # pers_add_fail() { for cand in ${P_ROOT}/_*; do if [ -f "${cand}/$1" ]; then rm -f "${cand}/$1"; fi done fail "'$1' could not be added"; } ############################################################################## # pers_remove # # Remove a file from all personalities in the repository. # pers_remove() { if [ ! -f "${P_BASE}/$1" ]; then fail "'$1' is not part of the Personality System"; fi # OK, it should be there; nuke whatever we can find for cand in ${P_ROOT}/_*; do if [ -f "${cand}/$1" ]; then rm -f "${cand}/$1"; fi done } ############################################################################## # pers_list # # List all of the files that comprise the system personality. # pers_list() { echo "Current personalities:" for pers in `cat "${P_LIST}"`; do echo " ${pers}"; done echo "Files in system personality:" for file in `cat "${P_FILES}"`; do echo " ${file}" done } ############################################################################## # pers_init # # Initialise the personality collection; refuse to do so if there is # already one in place, or something else occupying the root path. # pers_init() { if [ -e "${P_ROOT}" ]; then fail "cannot initialise, '${P_ROOT}' already exists" fi # Create the repository with no files, and no current personality mkdir -p "${P_ROOT}" mkdir -p "${P_BASE}" } ############################################################################## # pers_reindex # # Clean out any empty directories in the repository. This is achieved # by silently trying to rmdir everything that looks like a directory # under any personality. # # Then rebuild the list of files that comprise the system personality, # so that the select and menu functions work. # pers_reindex() { # Remove empty directories for cand in ${P_ROOT}/_*; do find -dX "${cand}/." -type d | xargs rmdir >/dev/null 2>&1 done # Regenerate the files list find -X "${P_BASE}" -type f | sed "s%${P_BASE}%%" > "${P_FILES}" # regenerate the personalities list ls -d "${P_ROOT}/_"* | sed "s%${P_ROOT}/_%%" > "${P_LIST}" } ############################################################################## # usage # # Emit a (hopefully) helpful diagnostic and exit # usage() { echo "${scriptname}: incorrect argument(s)" echo "" echo " Usage is ${scriptname} , where valid commands are :" echo " menu [] Invoke the menu-driven personality selector" echo " select Select a specific personality" echo " restore Restore the current personality from the saved version" echo " save Save the current personality" echo " saveas Save the current personality under a new name" echo " create Create a new personality from the base" echo " delete Delete a personality" echo " add Add a new file" echo " remove Remove a file" echo " list List all files" echo " init Initialise the Personality System" echo "" exit 2; } ############################################################################## # fail # # Emit an error message to stderr and exit # fail () { echo "${scriptname}: $1"; exit 1; } ############################################################################## # Now we have parsed everything, start. pers_main $1 $2 $3 $4; exit 0; --==_Exmh_21172141880--