1
0
Files
irix-657m-src/eoe/cmd/initpkg/mrnetrc.sh
2022-09-29 17:59:04 +03:00

832 lines
20 KiB
Bash
Executable File

#! /bin/sh
#Tag 0x00000f00
#ident "$Revision $"
. mrprofrc
# mrnetrc {start|stop|netisup|forcestart [askipaddr]|sethostname|setipaddr
# |addhost hostname|validaddr ipaddr|sethostaddr hostname ipaddr
# |gethostaddr hostname}
#
# Invoke with one of following:
#
# start Copy up /root net config files and try to
# start network. Don't fuss or interact if fails.
#
# stop Invoke /etc/init.d/network stop.
#
# netisup Return success iff network seems to be up.
#
# forcestart Set hostname, ip addr and run network start.
# Ok to ask user for hostname and/or ipaddr,
# if unable to discover automatically.
#
# Expects to be called from inst if earlier
# "mrnetrc start" failed to bring up networking,
# and user of inst tries to set "from" to a
# network address (has ':' in name). Assumes earlier
# "mrnetrc start" copied up an available network config
# files from the normal /root file system.
#
# If optional 2nd arg "askipaddr" is present,
# then don't guess the ipaddr, ask instead.
# This "mrnetrc forcestart askipaddr" case is
# used to implement "mrnetrc setipaddr", below.
#
# sethostname Ask user for this systems hostname and
# place in /etc/sys_id. Then do forcestart.
#
# setipaddr Ask user for this hosts ipaddr and put
# into /etc/hosts (first removing any
# conflicting entries with same hostname).
# Then do forcestart. Actually implemented
# by just calling "mrnetrc forcestart askipaddr".
#
# addhost hostname
# If /etc/hosts doesn't already have an entry
# for specified hostname, then ask for ipaddr
# of that host, and append an entry for it in
# /etc/hosts.
#
# validaddr ipaddr
# Exit 1 if the ip address is bogus (see below),
# otherwise exit 0.
#
# sethostaddr hostname ipaddr
# Set the ip address of a host in /etc/hosts
# gethostaddr hostname
# Get the ip address of a host in /etc/hosts,
# returns "0" if not found.
#
# Ignore SIGHUP. This is needed so that processes that haven't had
# a change to run long enough to daemonize won't get killed when
# this script exits.
#
trap "" 1
#-------------- useful functions ---------------------
# comment_filter
#
# this sed script strips comment and empty lines.
comment_filter()
{
sed -n -e '/#.*/s///' -e '/[ ]*$/s///' -e /./p
# beware ^^^^^^^ tab character
}
# gethostidbyname hostname
#
# Given a host or alias name that is in /etc/hosts, print the
# corresponding ip address of the first matching line on stdout.
#
# If hostname not found in /etc/hosts, print "0". Comments beginning
# with '#' and ending with '\n' are suppressed. Lines with < 2 fields
# (space or tab separated) are ignored. This should match the way
# gethostbyname(3N) parses /etc/hosts.
gethostidbyname()
{
test -s "/etc/hosts" || { echo 0; return; }
comment_filter < /etc/hosts | awk '
BEGIN { ipaddr = 0; }
NF >= 2 {
for (i = 2; i <= NF; i++) {
if ($i == "'"$1"'") {
ipaddr = $1
exit
}
}
}
END { print ipaddr }
'
}
# gethostnamebyipaddr ipaddr
#
# Given an ip address, print the first corresponding hostname
# for it in /etc/hosts. If not found, print empty string.
gethostnamebyipaddr()
{
test -s "/etc/hosts" || return
comment_filter < /etc/hosts | awk '
NF >= 2 && $1 == "'"$1"'" {
print $2
exit
}
'
}
# removehostsconflicts host
#
# Typically, only first /etc/hosts entry for a specified host
# is recognized. Remove all lines matching on "$host", so that
# they do not conflict. Call before appending entry to the
# end of /etc/hosts.
# Treats comment lines like any other: if any field but the first
# matches "$host", remove the line. Would be best if we treated
# comments special: passing them all through, unless they were a
# comment on a line that was being removed. This however is a
# level of subtlety that is ill-defined, hard to do, and not worth it.
removehostsconflicts()
{
test -f /etc/hosts || return
awk < /etc/hosts > /etc/hosts.tmp '
{ for (i = 2; i <= NF; i++) {
if ($i == "'"$1"'")
next
}
}
{ print }
'
mv /etc/hosts.tmp /etc/hosts
}
# bogus ipaddr
#
# Decide if ip address bogus, such as 0, 0.0.0.0, 127.*.*.*
# (localhost) and 192.0.2.1 (test).
# Return 0 for success -- meaning _is_ bogus.
# Return 1 for failure -- meaning is not bogus.
#
# Set variable $reason with explanation, so that caller
# can if it chooses display the reason an address is bogus.
bogus()
{
inet_aton "$1" || {
reason='\nInvalid ascii Internet address representation: <'"$1"'>
Typical address is up to 4 . separated numbers. Example: 192.0.2.2'
return 0;
}
case "$1" in
0|0x0|0.0|0.0.0|0.0.0.0)
reason='\nInternet address of zero <'"$1"'> not usually valid'
return 0
;;
127.*.*.*)
reason='\nInternet addresses 127.*.*.* reserved for loopback'
return 0
;;
192.0.2.1)
reason='\nInternet address <192.0.2.1> is for testing. It loops back by default'
return 0
;;
"")
reason='\nPlease specify non-empty Internet address'
return 0;
;;
*)
return 1
;;
esac
}
# confirm message ...
#
# Display message. Ask "Are you sure".
# Return with success if user answers yes.
confirm()
{
echo "$*"
echo '\n\tAre you sure? [y/n] (n): \c'
read line
case "$line" in
[yY]*) return 0;;
*) return 1;;
esac
}
copynetfiles()
{
(
cp /root/etc/sys_id /etc/sys_id
cp /root/etc/config/ifconfig-*.options /etc/config
cp /root/usr/etc/resolv.conf /etc/resolv.conf # old path
cp /root/etc/resolv.conf /etc/resolv.conf # new path
cp /root/etc/config/netif.options /etc/config/netif.options
chmod +x /etc/config/netif.options # old inst does "test -x" !?!
cp /root/etc/hosts /etc/hosts ||
echo "127.0.0.1 localhost loghost" > /etc/hosts
chmod +x /etc/hosts # old inst does "test -x" !?!
chkconfig -f network on
) 2>/dev/null
}
savenetfiles()
{
(
mkdir /etc/config/.savedconfig
mv /etc/config/ifconfig-*.options /etc/config/.savedconfig
mv /etc/config/netif.options /etc/config/.savedconfig
mv /etc/sys_id /etc/.sys_id.saved
cp /etc/hosts /etc/.hosts.saved
) 2>/dev/null
}
restorenetfiles()
{
(
rm /etc/config/ifconfig-*.options /etc/hosts /etc/sys_id
mv /etc/config/.savedconfig/ifconfig-*.options /etc/config
mv /etc/config/.savedconfig/netif.options /etc/config
mv /etc/.hosts.saved /etc/hosts
mv /etc/.sys_id.saved /etc/sys_id
rm -rf /etc/config/.savedconfig
) 2>/dev/null
}
# $1 is the default (builtin) interface name
restartnetwork()
{
chkconfig -f network on
chkconfig verbose
isverbose=$?
# turn on verbose so we can inhibit that nasty graphical message
chkconfig -f verbose on
(
/etc/init.d/network stop
ifconfig $1 down
/etc/init.d/network start
) >/dev/null 2>&1
if test $isverbose -ne 0 ; then
chkconfig verbose off
fi
}
defaultinterface()
{
# this works even if there are interfaces without miniroot drivers
hinv -c network | sed -ne 's/^Integr.* \([a-z][a-z]*0\),.*$/\1/p'
}
# return the number of interfaces (excluding lo0)
numinterfaces()
{
ifconfig -a | awk '/^[a-z][a-z]*[0-9][0-9]*:/ {num += 1;}
/^lo0:/ {num -= 1;}
END {print num;}'
}
ishex()
{
echo "$1" | grep -i "^0x[0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f]$" > /dev/null
}
# $1 is the interface name
# $2 is the optional pathname prefix (probably /root)
getinterfacenum()
{
test $# -eq 0 && return
interfacefile="/etc/config/netif.options"
if test $# -gt 1 ; then
interfacefile=$2$interfacefile
fi
(
# mimic what happens in /etc/init.d/network script so we can
# accurately predict what ifconfig options file will have the
# integral interface information
if_num=9
if ( ifconfig ipg0 || ifconfig xpi0 || ifconfig rns0 ) >/dev/null 2>&1
then
if2name="$1"
num=2
else
if1name="$1"
num=1
fi
test -s "$interfacefile" || { echo -n $num; return; }
. "$interfacefile"
num=1
while test $num -le $if_num; do
eval _ifname='$'if${num}name
if test "$_ifname" = "$1" ; then
echo -n $num
return
fi
num=`expr $num + 1`
done
)
}
# $1 is ip address
getclassdefaultnetmask()
{
test $# -eq 1 || return
echo "$1" | nawk -F\. '{
if ($1 < 128) {print "0xff000000"}
else if ($1 < 192) {print "0xffff0000"}
else if ($1 < 224) {print "0xffffff00"}
else {print "0xffffffff"}
}'
}
# $1 is optional path prefix (ie. /root)
getnetmask()
{
nvramnetmask=`nvram netmask 2>/dev/null`
if test $nvramnetmask && \
( ishex "$nvramnetmask" || ! bogus "$nvramnetmask" ) ; then
echo -n "$nvramnetmask"
return
fi
interface=`defaultinterface`
prefix=""
if test $# -gt 0 ; then
prefix="$1"
fi
num=`getinterfacenum "$interface" "$prefix"`
test "$num" || exit 1
ethnetmask=0
ifconfigname=$prefix/etc/config/ifconfig-"$num".options
if test -s "$ifconfigname" ; then
configoptions="`cat $ifconfigname 2> /dev/null`"
set $configoptions
while test $# -gt 1 ; do
if test "$1" = "netmask" ; then
ethnetmask=$2
break
fi
shift
done
fi
# debugging code was useful
# echo 1>&2 mrnetrc getnetmask: ethnetmask= "\"$ethnetmask\""
if ishex "$ethnetmask" || ! bogus "$ethnetmask" ; then
echo -n "$ethnetmask"
fi
}
# $1 is hostname
# $2 is ip address
# $3 is interface name
# $4 is netmask
buildnetworkfiles()
{
test $# -eq 4 || return 1
savenetfiles
echo "$1" > /etc/sys_id
hostname "$1"
echo "if1name=$3\nif_num=1\nif1addr=$1\n" > /etc/config/netif.options
if test -n "$4" ; then
echo netmask "$4" > /etc/config/ifconfig-1.options
fi
removehostsconflicts "$1"
echo "$2 $1" >> /etc/hosts
}
# converts $1 IP address (or netmask) argument to hex format
tohex()
{
echo $1 | awk -F. '
/^0x/ && NF == 1 {a=substr($1,3);printf "%s\n",a; exit 0}
NF == 2 {printf "%02x%06x\n",$1,$2; exit 0}
NF == 3 {printf "%02x%02x%04x\n",$1,$2,$3; exit 0}
NF == 4 {printf "%02x%02x%02x%02x\n",$1,$2,$3,$4; exit 0}
{exit 1}
'
}
# $1 is the hostname ( if empty minimal networking is started using ifconfig )
# $2 is the root path where to look for network config files (ie /root or "")
# $2 is used to determine the netmask in the event nvram netmask is not set
setupbuiltinnetworking()
{
test $# -eq 2 || return 1
etheripaddr=`nvram netaddr 2>/dev/null || echo 0`
bogus "$etheripaddr" && return 1
interface=`defaultinterface`
test $interface || return 1
ethernetmask=`getnetmask "$2"`
# debugging code
# echo "mrnetrc: setupbuiltinnetworking \"$interface\" \"$etheripaddr\" \"$ethernetmask\""
# if no hostname provided we should configure networking manually and
# bypass the network script entirely since it will put us in standalone
if test -z "$1" ; then
killall routed
if test "$ethernetmask" ; then
ifconfig "$interface" inet "$etheripaddr" primary netmask "$ethernetmask"
else
ifconfig "$interface" inet "$etheripaddr" primary
fi
hostid 0x`tohex $etheripaddr`
if chkconfig routed ; then
routed_opts="`cat /etc/config/routed.options 2> /dev/null`"
routed "$routed_opts"
fi
if mrinterface ; then
if test -s /etc/sys_id ; then
hostname `sed -n p /etc/sys_id`
removehostsconflicts `hostname`
echo "$etheripaddr `hostname`" >> /etc/hosts
fi
return 0
fi
return 1
fi
# otherwise, save off all the old networking files and create
# new ones with the new derived values and then restart networking
buildnetworkfiles $1 $etheripaddr $interface $ethernetmask
restartnetwork $interface
hostid 0x`tohex $etheripaddr`
removehostsconflicts $1
echo "$etheripaddr $1" >> /etc/hosts
if ! mrinterface ; then
restorenetfiles
if test -f /etc/sys_id ; then
hostname `sed -n p /etc/sys_id`
fi
return 1
fi
return 0
}
#-------------- main procedures -----------------------
case "$1" in
start)
# This is a no-op in custom mode, since minimal networking has
# already started if we got this far.
if mrcustomrc iscustom ; then
exit 0
fi
# Best effort network start. Copy up user's network
# configuration from /root, and run "network start"
# Don't fuss or interact if unable to do some or all of this.
# If later on, we decide we really must have networking on,
# then call "mrnetrc forcestart" at that time.
copynetfiles
if test -f /etc/sys_id -a -f /root/etc/hosts
then
# Use "sed -n p" instead of "cat" because cat command
# can fail, writing to a fifo, when the next fifo inode
# number assigned by the kernel happens to match the
# inode number of the file being cat'd. The failure
# complains: Input/output files '/etc/sys_id' identical
hostname `sed -n p /etc/sys_id`
/etc/init.d/network start
fi
;;
stop)
/etc/init.d/network stop
;;
netisup)
# If network already started successfully, return success (0) else failure.
#
# Use mrinterface to check for the network interfaces that are UP.
# mrinterface will return 3 possible values : -1 = error
# 0 = success (network UP - found network interface)
# 1 = failure
#
mrinterface
;;
forcestart)
# Note the NVRAM's netaddr. We might use this to guess
# the desired hostname, if sys_id doesn't help. And
# later we might use it to determine this hosts ip address,
# if the address (if any) listed for this host in /etc/hosts
# is bogus.
nvramipaddr=`nvram netaddr 2>/dev/null || echo 0`
# Determine hostname from /etc/sys_id, or by looking up
# the NVRAM's netaddr in the /etc/hosts file, or from
# asking user. Then put it in /etc/sys_id, if need be.
# See explanation above for use of "sed -n p" instead of "cat".
test -s /etc/sys_id && host=`sed -n p /etc/sys_id` || {
# Try to find a hostname by looking up nvram's netaddr
# in /etc/hosts.
host=`gethostnamebyipaddr "$nvramipaddr"`
# If that came up empty, have to ask the user.
# We accept any non-zero length string.
while test -z "$host"
do
echo 'What is the hostname (system name) of your machine? \c'
read host
if [ x"$host" = x"!" ]; then
echo "Type exit when ready to continue"
/bin/csh
host=
fi
done
echo "$host" > /etc/sys_id
}
# Set the system hostname
hostname "$host"
defaultint=`defaultinterface`
defaultnetmask=`getnetmask`
askuser=0
if test $# -eq 2 -a askipaddr = "$2" || \
test -z "$defaultint" || bogus "$nvramipaddr" ; then
askuser=1
fi
# While still bogus, ask user if ok.
# If user confirms, quit asking.
if test "$askuser" -eq 1 ; then
if test `numinterfaces` -eq 1 ; then
interface=$defaultint
else
interface=
fi
while ! ifconfig "$interface" >/dev/null 2>&1; do
if test -n "$interface" ; then
confirm Using network interface "$interface".' \c' && break
fi
if test -z "$defaultint" ; then
echo What network interface would you like to configure? '\c'
else
echo What network interface would you like to configure?
echo Press Enter for builtin interface [$defaultint] '\c'
fi
read interface
if test -z "$interface" ; then
interface=$defaultint
fi
if [ x"$interface" = x"!" ]; then
echo "Type exit when ready to continue"
/bin/csh
interface=
fi
done
ipaddr=
while bogus "$ipaddr" ; do
if test -n "$ipaddr" ; then
echo "$reason"
confirm Using network address: "$ipaddr" for: "$host".' \c' && break
fi
echo What is the network address of "$host"? '\c'
read ipaddr
if [ x"$ipaddr" = x"!" ]; then
echo "Type exit when ready to continue"
/bin/csh
ipaddr=
fi
done
else
interface=$defaultint
ipaddr=$nvramipaddr
fi
if test -z "$defaultnetmask" -o "$nvramipaddr" != "$ipaddr" -o \
"$interface" != "$defaultint" ; then
netmask=
while ! ishex "$netmask" && bogus "$netmask" ; do
if test -n "$netmask" ; then
echo "$netmask" is an invalid netmask.
fi
defaultnetmask=`getclassdefaultnetmask "$ipaddr"`
echo What is the netmask for "$ipaddr"?
echo "Press Enter for the IP class default [$defaultnetmask]: \c"
read netmask
if test -z "$netmask" ; then
netmask="$defaultnetmask"
break
fi
if [ x"$netmask" = x"!" ]; then
echo "Type exit when ready to continue"
/bin/csh
netmask=
fi
done
else
netmask=$defaultnetmask
fi
buildnetworkfiles "$host" "$ipaddr" "$interface" "$netmask"
echo Starting network with hostname: "$host", at ip address: "$ipaddr"
restartnetwork "$interface"
mrinterface
;;
sethostname)
# Ask the user for the hostname to set.
# We accept any non-zero length string.
host=
while test -z "$host"
do
echo 'What is the hostname (system name) of your machine? \c'
read host
if [ x"$host" = x"!" ]; then
echo "Type exit when ready to continue"
/bin/csh
host=
fi
done
echo "$host" > /etc/sys_id
# restart the network
exec $0 forcestart
echo Failed to restart the network 1>&2
;;
setipaddr)
exec $0 forcestart askipaddr
echo Failed to invoke $0 forcestart askipaddr 1>&2
;;
validaddr)
bogus "$2" && exit 1
exit 0
;;
sethostaddr)
bogus "$3" && exit 1
bogus "$2" || exit 1
removehostsconflicts "$2"
echo "$3 $2" >> /etc/hosts
;;
gethostaddr)
bogus "$2" || exit 1
gethostidbyname "$2"
;;
addhost)
# put entry for specified host (2nd arg) in /etc/hosts file.
test $# -eq 2 || exit
host=$2
# is this host already in hosts -- if so, nothing to do, just leave
hostipaddr=`gethostidbyname "$host"`
test $hostipaddr != 0 && exit 0
# if asked to add host by name that looks like an ipaddr,
# then do nothing - user provided host ipaddr instead of hostname,
# so don't need to translate name to ipaddr -- already is.
bogus "$host" || exit 0
# if this is the same host we booted from, get the address from bootp
tapedevice=`nvram tapedevice 2>/dev/null || echo 0`
boothost=`echo "$tapedevice" | sed -n 's;.*bootp()\([^ :]*\).*;\1;p'`
bootfile=`echo "$tapedevice" | sed -n 's;.*bootp()\([^ ()]*\).*;-b\1;p'`
if [ "$boothost" = "$host" ]; then
/usr/etc/bootpc -r $bootfile -x4 > /tmp/bootp$$ 2>/dev/null
if [ -s /tmp/bootp$$ ]; then
ipaddr=`sed -n 's/^bootpaddr=//p' /tmp/bootp$$`
fi
rm -f /tmp/bootp$$ > /dev/null 2>&1
bogus "$ipaddr" || {
echo "$ipaddr $host" >> /etc/hosts
exit 0
}
fi
# ask user for ipaddr of host
while : asking
do
echo What is the network address of "$host"? '\c'
read ipaddr
if [ x"$ipaddr" = x"!" ]; then
echo "Type exit when ready to continue"
/bin/csh
else
break;
fi
done
# While still bogus, ask user if ok.
# If user confirms, quit asking.
while bogus "$ipaddr"
do
echo "$reason"
confirm Using network address: "$ipaddr" for: "$host".' \c' && break
echo What is the network address of "$host"? '\c'
read ipaddr
if [ x"$ipaddr" = x"!" ]; then
echo "Type exit when ready to continue"
/bin/csh
ipaddr=
fi
done
# Now we can append our line to /etc/hosts
echo "$ipaddr $host" >> /etc/hosts
;;
safestart)
# basically like "start", but traps the output and if any errors
# occur, will shutdown and do a "setupbuiltinnetworking"
defaultint=`defaultinterface`
if test -s /root/etc/config/netif.options -a -s /root/etc/sys_id -a -s /root/etc/hosts ; then
# there's a chance that all the needed configuration files are valid
copynetfiles
hostname=`sed -n p /etc/sys_id`
hostname $hostname
restartnetwork "$defaultint"
fi
if ! mrinterface ; then
ifconfig "$defaultint" down
setupbuiltinnetworking "$hostname" /root
fi
mrinterface
;;
startdefaultinterface)
# the hostname and rbase of tree to look for network files (/root or "")
# if an empty hostname is provided, networking is configured manually
# using ifconfig rather than calling the network scripts
test $# -eq 3 || exit 1
setupbuiltinnetworking "$2" "$3"
;;
*)
echo "Usage: $0 {start|stop|netisup|forcestart [askipaddr]|sethostname|setipaddr|addhost hostname|validaddr ipaddr|sethostaddr host ipaddr|startdefaultinterface host rbase }"
;;
esac