#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos72X src/bos/usr/lib/nim/methods/c_sh_lib.sh 1.37.36.3 # # Licensed Materials - Property of IBM # # COPYRIGHT International Business Machines Corp. 1993,2021 # All Rights Reserved # # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # IBM_PROLOG_END_TAG # @(#)52 1.37.36.3 src/bos/usr/lib/nim/methods/c_sh_lib.sh, cmdnim, bos72X, x2021_23B3 5/27/21 11:22:51 # # COMPONENT_NAME: CMDNIM # # FUNCTIONS: ./usr/lib/nim/methods/c_sh_lib.sh # # ORIGINS: 27 # # # (C) COPYRIGHT International Business Machines Corp. 1993, 1995, 1996 # All Rights Reserved # Licensed Materials - Property of IBM # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # this file contains shell library routines which are included by all NIM # shell scripts #---------------------------- local defines -------------------------------- PROG=${0} PROGNAME=${PROG##*/} [[ ${0} = /SPOT/?* ]] && SPOT=/SPOT || SPOT="" TMPDIR=/tmp/_nim_dir_$$ ERR=${TMPDIR}/err OLD_IFS=${IFS} C_ERRMSG_MSG=0 C_ERRMSG_ERR=1 #---------------------------- include file for NIM error message definitions . ${NIM_METHODS}/cmdnim_errors.shh #---------------------------- Export this variable so commands that do RSH can #---------------------------- utilize it in the Kerberos 5 arena. export K5MUTE=1 #---------------------------- NIM specific stuff REQUIRED_TMP_SPACE=2048 NIM_CLIENT_PACKAGE="bos.sysmgt.nim.client" NIM_SPOT_PACKAGE="bos.sysmgt.nim.spot" MASTER_UID=root MSG_MISSING_BOOTI="network boot images" SPOT_SERVER_OPTIONS="\ ${NIM_CLIENT_PACKAGE} \ bos.net.tcp.client \ bos.net.nfs.client" #--------------------------------- README ------------------------------------- # a SPOT is a very important NIM resource which is used to support all network # boot operations # in order to construct a SPOT, many optional packages are required # here's why they're needed: # bos.sysmgt.nim.client : required to support NIM operations # bos.sysmgt.nim.spot : required to support network boot # bos.net.nfs.client : required for NFS support # bos.net.tcp.client : network interface support # bos.net.tcp.smit : tcpip SMIT screens # bos.diag : required for diagnostic support # bos.sysmgt.serv_aid : required for diagnostic boot # bos.sysmgt.sysbr : required to support standalone install # bos.sysmgt.smit : required for diskless/dataless clients # bos.terminfo : required for diskless/dataless term support # devices.all : NIM needs all the device support it can get. # this is important because NIM has no # knowledge about device support needed by # any NIM client and, if a client needs # support for a device which the SPOT # doesn't have, then the network boot # operation being performed MIGHT fail # therefore, all device support is needed # The following is a list of fileset pairs from which a member from each pair # should be installed in a SPOT. The first in the list of pairs that is # found on the installation media will be appended to the list passed to # the installp command. # bos.rte.up(4.1), bos.up (>=4.2) : required to support diskless/dataless boot # bos.rte.mp(4.1), bos.mp (>=4.2) : required to support standalone install # The list of filesets to use for DEFAULT_SPOT_OPTIONS may later be # changed by the routine set_option_lists. #Common packages found in POWER version/releases #-------------------------------- DEFAULT_SPOT_COMMON_PPC="\ ${NIM_CLIENT_PACKAGE} \ ${NIM_SPOT_PACKAGE} \ bos.net.nfs.client \ bos.net.tcp.client \ bos.net.tcp.smit \ bos.diag \ bos.sysmgt.serv_aid \ bos.sysmgt.sysbr \ bos.sysmgt.smit \ bos.terminfo \ devices.all" #-------------------------------- DEFAULT_SPOT_OPTIONS_41="\ ${DEFAULT_SPOT_COMMON_PPC} \ bos.rte.up \ bos.rte.mp" DEFAULT_SPOT_OPTIONS_42="\ ${DEFAULT_SPOT_COMMON_PPC} \ bos.up \ bos.mp" DEFAULT_SPOT_OPTIONS_43="\ ${DEFAULT_SPOT_OPTIONS_42} \ bos.64bit" DEFAULT_SPOT_OPTIONS_50="\ ${DEFAULT_SPOT_OPTIONS_43}" DEFAULT_SPOT_OPTIONS_51="\ ${DEFAULT_SPOT_OPTIONS_43} \ rpm.rte" DEFAULT_SPOT_OPTIONS_52="\ ${DEFAULT_SPOT_OPTIONS_43}" DEFAULT_SPOT_OPTIONS_53="\ ${DEFAULT_SPOT_COMMON_PPC} \ bos.mp \ bos.mp64 \ bos.64bit" DEFAULT_SPOT_OPTIONS_61="\ ${DEFAULT_SPOT_COMMON_PPC} \ bos.mp64 \ bos.64bit \ bos.wpars \ mcr.rte" DEFAULT_SPOT_OPTIONS_71="\ ${DEFAULT_SPOT_COMMON_PPC} \ bos.mp64 \ bos.64bit \ bos.wpars \ mcr.rte" DEFAULT_SPOT_OPTIONS="\ ${DEFAULT_SPOT_COMMON_PPC} \ bos.mp64 \ bos.64bit \ bos.wpars \ mcr.rte" #--------------------------------- README ------------------------------------- # in order to support install operations, NIM must have access to a directory # which contains all the images which will be required for an install # operation # the set of images which NIM requires is called "simages" ("s"upport "images") # if a NIM lpp_source has the complete set of these images, then it the # "simages" attribute will be added to the definition of the lpp_source # the SIMAGES_OPTIONS list is used when creating an lpp_source # the REQUIRED_SIMAGES list is used to determine whether an lpp_source gets # the "simages" attribute or not # # The default list of filesets to use for SIMAGES_OPTIONS and REQUIRED_SIMAGES # may later be changed by the routine set_option_lists. ############################################################################### # # Do not introduce any blank lines during the definition of any of the # SIMAGES_* variables. When the 'use_source_simages' attribute is set to 'yes' # during the define operation of an lpp_source, NIM extracts the SIMAGES_* # variables from this file using grep -p. Please see defect 746878 for more # details. # ############################################################################### #Common packages found in POWER version/releases #-------------------------------- SIMAGES_COMMON_PPC="\ bos \ bos.adt \ bos.iconv \ bos.net \ bos.diag \ bos.loc.iso \ bos.msg.en_US \ bos.sysmgt \ bos.terminfo.all \ bos.txt \ devices.all \ printers.rte \ xlC.rte \ X11.apps \ X11.base \ X11.fnt \ X11.loc.all \ X11.motif \ X11.msg.all \ X11.vsm" #------------------------------------------- #Common packages found in POWER 43 &above #-------------------------------- SIMAGES_COMMON_43_ABOVE="\ bos.64bit \ bos.up \ bos.mp \ bos.help.msg.en_US \ ifor_ls.base \ perl.rte \ sysmgt.help.msg.en_US \ sysmgt.sguide \ sysmgt.websm \ sysmgt.msg.en_US.websm \ Tivoli_Management_Agent.client \ xlC.cpp \ xlC.msg.en_US.cpp \ _SPOT._.pre_i.usr.1.0.0.0 \ _SPOT._.post_i.usr.1.0.0.0" #------------------------------------------- SIMAGES_OPTIONS_41="\ ${SIMAGES_COMMON_PPC} \ bos.rte.up \ bos.rte.mp \ bos.ifor_ls \ bos.info.any \ bos.powermgt \ ipx \ X11.Dt \ X11.compat" SIMAGES_OPTIONS_42="\ ${SIMAGES_COMMON_PPC} \ bos.up \ bos.mp \ bos.info.any \ bos.ifor_ls \ bos.powermgt \ xlC.cpp \ X11.Dt \ X11.compat \ _SPOT._.pre_i.usr.1.0.0.0 \ _SPOT._.post_i.usr.1.0.0.0" SIMAGES_OPTIONS_43="\ ${SIMAGES_COMMON_PPC} \ ${SIMAGES_COMMON_43_ABOVE} \ bos.docsearch \ bos.docregister \ bos.html.en_US.topnav \ bos.powermgt \ ifor_ls.client \ IMNSearch.rte.httpdlite \ Java.rte \ xlC.msg.Ja_JP.cpp \ xlC.msg.ja_JP.cpp \ xlC.aix43 \ X11.Dt \ X11.compat" SIMAGES_OPTIONS_50="\ ${SIMAGES_COMMON_PPC} \ ${SIMAGES_COMMON_43_ABOVE} \ bos.mp64 \ bos.docsearch \ bos.docregister \ bos.html.en_US.topnav \ bos.man.en_US \ bos.perf \ bos.powermgt \ bos.svprint \ invscout.ldb \ invscout.rte \ rsct.core \ sysmgt.websm.webaccess \ IMNSearch.bld \ IMNSearch.rte \ IMNSearch.rte.httpdlite \ Java130.rte \ xlC.msg.Ja_JP.cpp \ xlC.msg.ja_JP.cpp \ xlC.aix50 \ X11.Dt \ X11.compat" SIMAGES_OPTIONS_51="\ ${SIMAGES_COMMON_PPC} \ ${SIMAGES_COMMON_43_ABOVE} \ bos.mh \ bos.mp64 \ bos.acct \ bos.docsearch \ bos.docregister \ bos.html.en_US.topnav \ bos.man.en_US \ bos.perf \ bos.powermgt \ bos.svprint \ invscout.com \ invscout.ldb \ invscout.rte \ rpm.rte \ rsct.core \ rsct.msg.en_US \ rsct.msg.EN_US \ sysmgt.help.en_US \ IMNSearch.bld \ IMNSearch.rte \ IMNSearch.rte.httpdlite \ Java130.rte \ xlC.aix50 \ X11.adt \ X11.Dt \ X11.samples \ csm.core \ csm.client" SIMAGES_OPTIONS_52="\ bos.64bit \ bos \ bos.acct \ bos.adt \ bos.cdmount \ bos.diag \ bos.help.msg.en_US \ bos.iconv \ bos.loc.iso \ bos.man.en_US \ bos.mh \ bos.mp \ bos.mp64 \ bos.msg.en_US \ bos.net \ bos.perf \ bos.suma \ bos.sysmgt \ bos.terminfo.all \ bos.txt \ bos.up \ csm.client \ csm.core \ csm.diagnostics \ csm.dsh \ csm.msg.en_US \ csm.msg.EN_US \ devices.all \ ifor_ls.base \ invscout.com \ invscout.ldb \ invscout.rte \ lum.base \ lum.msg.en_US \ perl.libext \ perl.rte \ printers.rte \ rpm.rte \ rsct.core \ rsct.msg.en_US \ rsct.msg.EN_US \ Tivoli_Management_Agent.client \ xlC.aix50 \ xlC.cpp \ xlC.msg.en_US.cpp \ xlC.rte \ _SPOT._.pre_i.usr.1.0.0.0 \ _SPOT._.post_i.usr.1.0.0.0" SIMAGES_OPTIONS_53="\ bos.64bit \ bos \ bos.acct \ bos.adt \ bos.alt_disk_install \ bos.atm \ bos.cdmount \ bos.diag \ bos.dlc \ bos.help.msg.en_US \ bos.iconv \ bos.loc.iso \ bos.mh \ bos.mp \ bos.mp64 \ bos.msg.en_US \ bos.net \ bos.perf \ bos.pmapi \ bos.suma \ bos.swma \ bos.sysmgt \ bos.terminfo.all \ bos.txt \ csm.client \ csm.core \ csm.deploy \ csm.diagnostics \ csm.dsh \ csm.msg.en_US \ csm.msg.EN_US \ devices.all \ ifor_ls.base \ ifor_ls.html.en_US \ infocenter.man.EN_US.commands \ invscout.com \ invscout.ldb \ invscout.rte \ lum.base \ lum.msg.en_US \ perfagent.tools \ perl.libext \ perl.rte \ printers.rte \ rpm.rte \ rsct.core \ rsct.msg.en_US \ rsct.msg.EN_US \ Tivoli_Management_Agent.client \ xlC.aix50 \ xlC.cpp \ xlC.rte \ xlC.msg.en_US.cpp \ _SPOT._.pre_i.usr.1.0.0.0 \ _SPOT._.post_i.usr.1.0.0.0" SIMAGES_OPTIONS_61="\ bos.64bit \ bos \ bos.acct \ bos.adt \ bos.ae \ bos.aixpert.cmds \ bos.aso \ bos.cdmount \ bos.diag \ bos.help.msg.en_US \ bos.iconv \ bos.iocp \ bos.loc.iso \ bos.mh \ bos.mls \ bos.mp64 \ bos.msg.en_US \ bos.net \ bos.perf \ bos.perf.pmaix \ bos.pmapi \ bos.swma \ bos.sysmgt \ bos.terminfo.all \ bos.txt \ bos.wpars \ clic.rte \ csm.client \ csm.core \ csm.deploy \ csm.diagnostics \ csm.dsh \ csm.msg.en_US \ csm.msg.EN_US \ devices.all \ ICU4C.rte \ ifor_ls.base \ ifor_ls.html.en_US \ invscout.com \ invscout.ldb \ invscout.rte \ lum.base \ lum.msg.en_US \ mcr.rte \ perfagent.tools \ perl.libext \ perl.rte \ printers.rte \ rpm.rte \ rsct.core \ rsct.msg.en_US \ rsct.msg.EN_US \ security.acf \ Tivoli_Management_Agent.client \ wio.common \ wio.fcp \ wio.vscsi \ xlC.aix61 \ xlC.sup.aix50.rte \ xlC.cpp \ xlC.rte \ xlC.msg.en_US.cpp \ _SPOT._.pre_i.usr.1.0.0.0 \ _SPOT._.post_i.usr.1.0.0.0" SIMAGES_OPTIONS_71="\ bos.64bit \ bos \ bos.acct \ bos.adt \ bos.ae \ bos.aixpert.cmds \ bos.aso \ bos.cdmount \ bos.diag \ bos.help.msg.en_US \ bos.iconv \ bos.iocp \ bos.loc.iso \ bos.mh \ bos.mls \ bos.mp64 \ bos.msg.en_US \ bos.net \ bos.perf \ bos.perf.pmaix \ bos.pmapi \ bos.swma \ bos.sysmgt \ bos.terminfo.all \ bos.txt \ bos.wpars \ cdrtools.base \ cdrtools.man.en_US \ clic.rte \ devices.all \ ICU4C.rte \ invscout.com \ invscout.ldb \ invscout.rte \ mcr.rte \ perfagent.tools \ perl.libext \ perl.rte \ printers.rte \ rpm.rte \ rsct.core \ rsct.msg.en_US \ rsct.msg.EN_US \ security.acf \ Tivoli_Management_Agent.client \ wio.common \ wio.fcp \ wio.vscsi \ xlC.aix61 \ xlC.sup.aix50.rte \ xlC.cpp \ xlC.rte \ xlC.msg.en_US.cpp \ _SPOT._.pre_i.usr.1.0.0.0 \ _SPOT._.post_i.usr.1.0.0.0" SIMAGES_OPTIONS="\ bos.64bit \ bos \ bos.acct \ bos.adt \ bos.ae \ bos.aixpert.cmds \ bos.aso \ bos.cdmount \ bos.diag \ bos.help.msg.en_US \ bos.iconv \ bos.iocp \ bos.liveupdate \ bos.loc.iso \ bos.mh \ bos.mls \ bos.mp64 \ bos.msg.en_US \ bos.net \ bos.perf \ bos.perf.pmaix \ bos.pmapi \ bos.swma \ bos.sysmgt \ bos.terminfo.all \ bos.txt \ bos.wpars \ cdrtools.base \ cdrtools.man.en_US \ clic.rte \ devices.all \ ICU4C.rte \ invscout.com \ invscout.ldb \ invscout.rte \ mcr.rte \ perfagent.tools \ perl.libext \ perl.rte \ printers.rte \ rpm.rte \ rsct.core \ rsct.msg.en_US \ rsct.msg.EN_US \ security.acf \ wio.common \ wio.fcp \ wio.vscsi \ xlC.aix61 \ xlC.sup.aix50.rte \ xlC.cpp \ xlC.rte \ xlC.msg.en_US.cpp \ _SPOT._.pre_i.usr.1.0.0.0 \ _SPOT._.post_i.usr.1.0.0.0" # RPM packages #-------------------------------- SIMAGES_COMMON_RPMS="\ cdrecord* \ mkisofs*" SIMAGES_OPTIONS_RPMS_50="\ ${SIMAGES_COMMON_RPMS} \ mtools*" SIMAGES_OPTIONS_RPMS_51="\ ${SIMAGES_OPTIONS_RPMS_50}" SIMAGES_OPTIONS_RPMS_52="\ ${SIMAGES_COMMON_RPMS}" SIMAGES_OPTIONS_RPMS_53="\ ${SIMAGES_COMMON_RPMS}" SIMAGES_OPTIONS_RPMS_61="\ ${SIMAGES_COMMON_RPMS} \ expect* \ tcl* \ tk*" SIMAGES_OPTIONS_RPMS_71="\ expect* \ tcl* \ tk*" SIMAGES_OPTIONS_RPMS="\ expect* \ tcl* \ tk*" # Graphics packages #-------------------------------- SIMAGES_OPTIONS_GRAPHICS_52="\ bos.docregister \ bos.docsearch \ bos.ecc_client \ csm.gui.dcem \ Java14.sdk \ Java14.license \ X11.adt \ X11.apps \ X11.base \ X11.fnt \ X11.loc.all \ X11.motif \ X11.msg.all \ X11.samples \ X11.vsm \ sysmgt.help.en_US \ sysmgt.help.msg.en_US \ sysmgt.sguide \ sysmgt.websm" SIMAGES_OPTIONS_GRAPHICS_53="\ bos.aixpert \ bos.aixpert.cmds \ bos.aixpert.websm \ bos.ecc_client \ bos.esagent \ bos.iocp \ bos.perf.fdpr \ cas.agent \ csm.gui.dcem \ DirectorCommonAgent \ DirectorPlatformAgent \ ICU4C.rte \ infocenter.man.EN_US.files \ infocenter.man.EN_US.libs \ Java14.sdk \ Java14.license \ Java5.sdk \ lwi \ openssl.base \ openssl.license \ openssl.man.en_US \ perfagent.server \ sysmgt.cim.providers \ sysmgt.cim.smisproviders \ sysmgt.cimserver.pegasus \ tivoli.tivguid \ X11.adt \ X11.apps \ X11.base \ X11.fnt \ X11.loc.all \ X11.motif \ X11.msg.all \ X11.samples \ X11.vsm \ sysmgt.help.en_US \ sysmgt.help.msg.en_US \ sysmgt.sguide \ sysmgt.websm \ sysmgtlib.framework \ sysmgtlib.libraries" SIMAGES_OPTIONS_GRAPHICS_61="\ adde.v2.ethernet \ adde.v2.common \ adde.v2.diag \ adde.v2.rdma \ artex.base \ bos.ahafs \ bos.aixpert.websm \ bos.alt_disk_install \ bos.cdat \ bos.clvm \ bos.cluster \ bos.dlc \ bos.ecc_client \ bos.esagent \ bos.perf.fdpr \ bos.suma \ bos.xerces \ cache.mgt \ cas.agent \ csm.gui.dcem \ DirectorCommonAgent \ DirectorPlatformAgent \ expect.base \ expect.man.en_US \ infocenter.man.EN_US.commands \ infocenter.man.EN_US.files \ infocenter.man.EN_US.libs \ Java5.sdk \ Java5_64.sdk \ Java6.sdk \ Java7_64.jre \ Java7_64.sdk \ lwi \ openssl.base \ openssl.license \ openssl.man.en_US \ perfagent.server \ rsct.basic \ rsct.compat.basic \ rsct.compat.clients \ rsct.opt.stackdump \ rsct.opt.storagerm \ sysmgt.cim.providers \ sysmgt.cim.smisproviders \ sysmgt.cimserver.pegasus \ tcl.base \ tcl.man.en_US \ tivoli.tivguid \ tk.base \ tk.man.en_US \ X11.adt \ X11.apps \ X11.base \ X11.compat \ X11.fnt \ X11.loc.all \ X11.motif \ X11.msg.all \ X11.samples \ X11.vsm \ xlsmp.rte \ xlsmp.aix61.rte \ sysmgt.help.en_US \ sysmgt.help.msg.en_US \ sysmgt.pconsole \ sysmgt.sguide \ sysmgt.websm \ sysmgtlib.framework \ sysmgtlib.libraries" SIMAGES_OPTIONS_GRAPHICS_71="\ adde.v2.ethernet \ adde.v2.common \ adde.v2.diag \ adde.v2.rdma \ artex.base \ bos.ahafs \ bos.alt_disk_install \ bos.cdat \ bos.clvm \ bos.cluster \ bos.dlc \ bos.ecc_client \ bos.esagent \ bos.perf.fdpr \ bos.pfcdd \ bos.suma \ bos.xerces \ cache.mgt \ cas.agent \ DirectorCommonAgent \ DirectorPlatformAgent \ expect.base \ expect.man.en_US \ infocenter.man.EN_US.commands \ infocenter.man.EN_US.files \ infocenter.man.EN_US.libs \ Java5.sdk \ Java5_64.sdk \ Java6.sdk \ Java7_64.jre \ Java7_64.sdk \ Java8.jre \ Java8.sdk \ Java8_64.jre \ Java8_64.sdk \ lwi \ ntp.rte \ openssl.base \ openssl.license \ openssl.man.en_US \ perfagent.server \ rsct.basic \ rsct.compat.basic \ rsct.compat.clients \ rsct.opt.stackdump \ rsct.opt.storagerm \ sysmgt.cfgassist \ sysmgt.cim.providers \ sysmgt.cim.smisproviders \ sysmgt.cimserver.pegasus \ tcl.base \ tcl.man.en_US \ tivoli.tivguid \ tk.base \ tk.man.en_US \ X11.adt \ X11.apps \ X11.base \ X11.compat \ X11.fnt \ X11.loc.all \ X11.motif \ X11.msg.all \ X11.samples \ X11.vsm \ xlsmp.rte \ xlsmp.aix61.rte \ sysmgt.pconsole \ sysmgtlib.framework \ sysmgtlib.libraries" SIMAGES_OPTIONS_GRAPHICS="\ adde.v2.ethernet \ adde.v2.common \ adde.v2.diag \ adde.v2.rdma \ artex.base \ bos.ahafs \ bos.alt_disk_install \ bos.cdat \ bos.clvm \ bos.cluster \ bos.dlc \ bos.dsc \ bos.ecc_client \ bos.esagent \ bos.hdcrypt \ bos.kmip_client \ bos.net.tcp.adt \ bos.net.tcp.bind \ bos.net.tcp.bind_utils \ bos.net.tcp.bootp \ bos.net.tcp.cdp \ bos.net.tcp.client \ bos.net.tcp.client_core \ bos.net.tcp.dfpd \ bos.net.tcp.dhcp \ bos.net.tcp.dhcpd \ bos.net.tcp.ftp \ bos.net.tcp.ftpd \ bos.net.tcp.gated \ bos.net.tcp.imapd \ bos.net.tcp.mail_utils \ bos.net.tcp.ntp \ bos.net.tcp.ntpd \ bos.net.tcp.pop3d \ bos.net.tcp.pxed \ bos.net.tcp.rcmd \ bos.net.tcp.rcmd_server \ bos.net.tcp.sendmail \ bos.net.tcp.server \ bos.net.tcp.server_core \ bos.net.tcp.slip \ bos.net.tcp.slp \ bos.net.tcp.smit \ bos.net.tcp.snmp \ bos.net.tcp.snmpd \ bos.net.tcp.syslogd \ bos.net.tcp.tcpdump \ bos.net.tcp.telnet \ bos.net.tcp.telnetd \ bos.net.tcp.tftp \ bos.net.tcp.tftpd \ bos.net.tcp.timed \ bos.net.tcp.traceroute \ bos.net.tcp.x500 \ bos.perf.fdpr \ bos.pfcdd \ bos.suma \ bos.xerces \ cache.mgt \ expect.base \ expect.man.en_US \ infocenter.man.EN_US.commands \ infocenter.man.EN_US.files \ infocenter.man.EN_US.libs \ ios.vnet \ Java8_64.jre \ Java8_64.sdk \ Java7_64.jre \ Java7_64.sdk \ Java6.sdk \ libc++.rte \ ntp.rte \ openssh.base \ openssh.license \ openssh.man.en_US \ openssh.msg.en_US \ openssl.base \ openssl.license \ openssl.man.en_US \ perfagent.server \ rsct.basic \ rsct.compat.basic \ rsct.compat.clients \ rsct.opt.stackdump \ rsct.opt.storagerm \ sysmgt.cfgassist \ tcl.base \ tcl.man.en_US \ tivoli.tivguid \ tk.base \ tk.man.en_US \ X11.adt \ X11.apps \ X11.base \ X11.compat \ X11.fnt \ X11.loc.all \ X11.motif \ X11.msg.all \ X11.samples \ X11.vsm \ xlsmp.rte \ xlsmp.aix61.rte \ sysmgtlib.framework \ sysmgtlib.libraries" #Common packages found in POWER version/releases #-------------------------------- REQUIRED_COMMON_PPC="\ bos \ bos.net \ bos.diag \ bos.sysmgt \ bos.terminfo \ bos.terminfo.all.data \ devices.graphics.all \ devices.scsi.all \ devices.tty.all \ xlC.rte" #----------------------------------------- REQUIRED_SIMAGES_41="\ ${REQUIRED_COMMON_PPC} \ devices.buc.all \ devices.mca.all \ devices.base.all \ devices.rs6ksmp.base \ devices.sio.all \ devices.sys.all \ bos.rte.up \ bos.rte.mp" REQUIRED_SIMAGES_42="\ ${REQUIRED_COMMON_PPC} \ devices.buc.all \ devices.mca.all \ devices.base.all \ devices.rs6ksmp.base \ devices.sio.all \ devices.sys.all \ bos.up \ bos.mp \ devices.common.all" REQUIRED_SIMAGES_43="\ ${REQUIRED_SIMAGES_42} \ bos.64bit" REQUIRED_SIMAGES_50="\ ${REQUIRED_SIMAGES_43}" REQUIRED_SIMAGES_51="\ ${REQUIRED_SIMAGES_43}" REQUIRED_SIMAGES_52="\ ${REQUIRED_COMMON_PPC} \ bos.up \ bos.mp \ devices.common.all \ bos.64bit" REQUIRED_SIMAGES_53="\ ${REQUIRED_COMMON_PPC} \ bos.mp \ devices.common.all \ bos.64bit" REQUIRED_SIMAGES_61="\ ${REQUIRED_COMMON_PPC} \ bos.mp64 \ devices.common.all \ bos.64bit \ bos.wpars \ bos.aixpert.cmds \ ifor_ls.base \ ICU4C.rte \ lum.base \ bos.mls \ perl.rte \ xlC.aix61" REQUIRED_SIMAGES_71="\ ${REQUIRED_COMMON_PPC} \ bos.mp64 \ devices.common.all \ bos.64bit \ bos.wpars \ bos.aixpert.cmds \ ICU4C.rte \ bos.mls \ perl.rte \ xlC.aix61" REQUIRED_SIMAGES="\ ${REQUIRED_COMMON_PPC} \ bos.mp64 \ devices.common.all \ bos.64bit \ bos.wpars \ bos.aixpert.cmds \ ICU4C.rte \ bos.mls \ perl.rte \ xlC.aix61" NIMINFO=/etc/niminfo NIM_AWK="${NIMPATH}/awk" NIM_CMDS="/usr/sbin" NIM="${NIM_CMDS}/nim" NIMCLIENT="${NIM_CMDS}/nimclient" NIMHTTP="${NIM_CMDS}/nimhttp" LSNIM="${NIM_CMDS}/lsnim" NIM_INSTP_UPDT_LIST="/tmp/NIM_instp_updt_list" MK_NETBOOT="/tmp/mk_netboot" NIM_STATUS="/tmp/.nim.stat" C_AT="${NIM_METHODS}/c_at" C_BOOTDISKHDR="${NIM_METHODS}/c_bootdiskhdr" C_CH_RHOST="${NIM_METHODS}/c_ch_rhost" C_CKROS_EMU="${NIM_METHODS}/c_ckros_emu" C_CKSPOT="${NIM_METHODS}/c_ckspot" C_CP_RESOLV="${NIM_METHODS}/c_cp_resolv" C_DUMPCHECK=${NIM_METHODS}/c_dumpcheck C_ERRMSG=${NIM_METHODS}/c_errmsg C_FILE_TRANSFER="${NIM_METHODS}/c_file_transfer" C_FUNCTION="${NIM_METHODS}/c_function" C_GETLEVEL="${NIM_METHODS}/c_getlevel" C_INSTALLP="${NIM_METHODS}/c_installp" C_MK_NIMCLIENT="${NIM_METHODS}/c_mk_nimclient" C_MKBOOTI="${NIM_METHODS}/c_mkbooti" C_MKDIR="${NIM_METHODS}/c_mkdir" C_MKPFILE=${NIM_METHODS}/c_mkpfile C_NIMINFO="${NIM_METHODS}/c_niminfo" C_RCP="${NIM_METHODS}/c_rcp" C_RMDIR=${NIM_METHODS}/c_rmdir C_RSH="${NIM_METHODS}/c_rsh" C_SCRIPT=${NIM_METHODS}/c_script C_STAT=${NIM_METHODS}/c_stat C_SYNC_ROOT=${NIM_METHODS}/c_sync_root C_TIME_STAMP=${NIM_METHODS}/c_time_stamp NIM_CHROOT_LIBS_BASE=/usr/lib/._spot_libs_@_71438 NIM_CHROOT_LIBS1=${NIM_CHROOT_LIBS_BASE}/usr/ccs/lib NIM_CHROOT_LIBS2=${NIM_CHROOT_LIBS_BASE}/usr/lib NIM_CHROOT_LIBS_LINKS_BASE=/usr/lib/._spot_libs_links_@_71439 NIM_CHROOT_LIBS_LINKS1=${NIM_CHROOT_LIBS_LINKS_BASE}/usr/ccs/lib NIM_CHROOT_LIBS_LINKS2=${NIM_CHROOT_LIBS_LINKS_BASE}/usr/lib SET_CHROOT_LIBPATH="export LIBPATH=${NIM_CHROOT_LIBS_LINKS1}:${NIM_CHROOT_LIBS_LINKS2}:${NIM_CHROOT_LIBS1}:${NIM_CHROOT_LIBS2}:/usr/ccs/lib:/usr/lib" UNSET_CHROOT_LIBPATH="unset LIBPATH" M_CHSTATE=${NIM_METHODS}/m_chstate M_FS=${NIM_METHODS}/m_fs LPP_NAME="./lpp_name" IMAGE_DATA="./image.data" LPP_NAME_IN_SPOT="./lpp/bos/inst_root/lpp_name" IMAGE_DATA_IN_SPOT="./lpp/bosinst/image.template" DEFAULT_REQUIRED_VERSION=4 DEFAULT_REQUIRED_RELEASE=0 BOS_PATH_ON_CDROM="installp/ppc/bos" BOS_PATH_ON_CDROM_OLD="usr/sys/inst.images/bos" LIC_PATH_ON_CDROM="usr/swlag" DEFAULT_PERMS="775" INST_ROOT="./lpp/bos/inst_root" INST_IMAGES="/usr/sys/inst.images" DEFAULT_GENCOPY_FLAGS="-bqXS" DEFAULT_INSTALLP_FLAGS="-agQX" DEFAULT_INSTALLP_OPTIONS="all" INSTALLP_LOG=/var/adm/ras/nim.installp LPPCHK_LOG=/var/adm/ras/nim.lppchk OFFSET_FOR_CDROM="/installp/ppc" OFFSET_FOR_CDROM_OLD="/usr/sys/inst.images" TFTPBOOT="/tftpboot" NIM_BACKUP_DIR="/export/nim/backups" SWAPNFS="swapnfs" INSTROOT_CUST_SZ=/tmp/.installp.root_sz #Used to track root size requirements #between c_instspot and c_sync_root #for /usr-SPOT inst_root. SCRIPT_LOG=/var/adm/ras/nim.script SHROOT_CUSTDIR="etc/.client_data" STATE_RUNNING=running PROTECTED_DIRS="/ /usr /var /tmp /home $TFTPBOOT" # NOTE: The following variable gets used by c_instspot when creating # a chroot environment. The value of IMAGES is the directory # over which the lpp_source will be mounted. This mount point # must NOT correspond to any existing filesystem on the server # or installp will fail because the stat system call fails # because it gets confused. So, we're using the process ID of # c_instspot in the hopes that it will be unique enough that # the server will not have a filesystem which uses that name IMAGES="/$$" NFS4_MNTDIR="/tmp/_.nim_mounts._" NFS4_LINKDIR="${NFS4_MNTDIR}/hostlinks" #---------------------------- AIX command pathnames INURID=${SPOT}/usr/lib/instl/inurid RCBOOT=${SPOT}/sbin/rc.boot BACKUP=${SPOT}/usr/sbin/backup BFFCREATE=${SPOT}/usr/sbin/bffcreate BOOTINFO=${SPOT}/usr/sbin/bootinfo BOOTPTODHCP=${SPOT}/usr/sbin/bootptodhcp BOSBOOT=${SPOT}/usr/sbin/bosboot CDCHECK=${SPOT}/usr/sbin/cdcheck CDEJECT=${SPOT}/usr/sbin/cdeject CDMOUNT=${SPOT}/usr/sbin/cdmount CDUMOUNT=${SPOT}/usr/sbin/cdumount CHDEV=${SPOT}/usr/sbin/chdev CHFS=${SPOT}/usr/sbin/chfs CHNFS=${SPOT}/usr/sbin/chnfs CHNFSEXP=${SPOT}/usr/sbin/chnfsexp CHROOT=${SPOT}/usr/sbin/chroot COMPRESS=${SPOT}/usr/bin/compress DSPMSG=${SPOT}/usr/bin/dspmsg GENCOPY="${SPOT}/usr/sbin/gencopy" GENINSTALL="${SPOT}/usr/sbin/geninstall -Z" INSTALLP="${SPOT}/usr/sbin/installp" INUTOC="${SPOT}/usr/sbin/inutoc" LINK=${SPOT}/usr/sbin/link LOOPMOUNT=${SPOT}/usr/sbin/loopmount LOOPUMOUNT=${SPOT}/usr/sbin/loopumount LSATTR=${SPOT}/usr/sbin/lsattr LSFS=${SPOT}/usr/sbin/lsfs MKBOOT=${SPOT}/usr/sbin/mkboot MKITAB=${SPOT}/usr/sbin/mkitab MKNFS=${SPOT}/usr/sbin/mknfs MKNFSEXP=${SPOT}/usr/sbin/mknfsexp MKTCPIP=${SPOT}/usr/sbin/mktcpip MOUNT=${SPOT}/usr/sbin/mount NAMERSLV=${SPOT}/usr/bin/namerslv REBOOT=${SPOT}/usr/sbin/reboot RESOLV_CONF="/etc/resolv.conf" RESTORE=${SPOT}"/usr/sbin/restbyname -Sq" ROUTE=${SPOT}"/usr/sbin/route" RSH=${SPOT}"/usr/bin/rsh" RMNFSEXP=${SPOT}/usr/sbin/rmnfsexp SAVEBASE=${SPOT}/usr/sbin/savebase SHUTDOWN=${SPOT}/usr/sbin/shutdown SM_INST=${SPOT}/usr/lib/instl/sm_inst UNLINK=${SPOT}/usr/sbin/unlink UNMOUNT=${SPOT}/usr/sbin/unmount ALOG=${SPOT}/usr/bin/alog AT=${SPOT}/usr/bin/at AWK=${SPOT}/usr/bin/awk BOOTLIST=${SPOT}/usr/bin/bootlist BOOTINFO=${SPOT}/usr/sbin/bootinfo BASENAME=${SPOT}/usr/bin/basename CAT=${SPOT}/usr/bin/cat CFGMGR=${SPOT}/usr/sbin/cfgmgr CHMOD=${SPOT}/usr/bin/chmod CHOWN=${SPOT}/usr/bin/chown CHSIGNPOLICY=${SPOT}/usr/sbin/chsignpolicy CHWPAR=${SPOT}/usr/sbin/chwpar CP=${SPOT}/usr/bin/cp CUT=${SPOT}/usr/bin/cut CPIO=${SPOT}/usr/bin/cpio DATE=${SPOT}/usr/bin/date DD=${SPOT}/usr/bin/dd DF=${SPOT}/usr/bin/df DIRNAME=${SPOT}/usr/bin/dirname DU="${SPOT}/usr/bin/du -x" ECHO=${SPOT}/usr/bin/echo EGREP=${SPOT}/usr/bin/egrep EXPR=${SPOT}/usr/bin/expr FGREP=${SPOT}/usr/bin/fgrep FILE=${SPOT}/usr/bin/file FIND=${SPOT}/usr/bin/find GREP=${SPOT}/usr/bin/grep HOSTCMD=${SPOT}/usr/bin/host HOSTNAME=${SPOT}/usr/bin/hostname INSTFIX=${SPOT}/usr/sbin/instfix INUUMSG=${SPOT}/usr/sbin/inuumsg LN=${SPOT}/usr/bin/ln LPPCHK=${SPOT}/usr/bin/lppchk LS=${SPOT}/usr/bin/ls LSDEV=${SPOT}/usr/sbin/lsdev LSLPP=${SPOT}/usr/bin/lslpp LSLV=${SPOT}/usr/sbin/lslv LSMKSYSB=${SPOT}/usr/bin/lsmksysb LSSAVEVG=${SPOT}/usr/bin/lssavevg LSSAVEWPAR=${SPOT}/usr/bin/lssavewpar LSWPAR=${SPOT}/usr/sbin/lswpar MKDEV=${SPOT}/usr/sbin/mkdev MKDIR=${SPOT}/usr/bin/mkdir MKISCSI=${SPOT}/usr/sbin/mkiscsi MKSSYS=${SPOT}/usr/bin/mkssys MKWPAR=${SPOT}/usr/sbin/mkwpar MV=${SPOT}/usr/bin/mv NM=${SPOT}/usr/bin/nm OD=${SPOT}/usr/bin/od ODMADD=${SPOT}/usr/bin/odmadd ODMCHANGE=${SPOT}/usr/bin/odmchange ODMDELETE=${SPOT}/usr/bin/odmdelete ODMGET=${SPOT}/usr/bin/odmget OSLEVEL=${SPOT}/usr/bin/oslevel PRTCONF=${SPOT}/usr/sbin/prtconf PS=${SPOT}/usr/bin/ps RECFGCT=${SPOT}/usr/sbin/rsct/install/bin/recfgct REFRESH=${SPOT}/usr/bin/refresh RESTWPAR=${SPOT}/usr/sbin/restwpar RM="${SPOT}/usr/bin/rm -f" RMDEV=${SPOT}/usr/sbin/rmdev RMDIR=${SPOT}/usr/bin/rmdir RMISCSI=${SPOT}/usr/sbin/rmiscsi RMITAB=${SPOT}/usr/sbin/rmitab RMSSYS=${SPOT}/usr/bin/rmssys RMWPAR=${SPOT}/usr/sbin/rmwpar SAVEWPAR=${SPOT}/usr/sbin/savewpar SED=${SPOT}/usr/bin/sed SLEEP=${SPOT}/usr/bin/sleep SLIBCLEAN=${SPOT}/usr/sbin/slibclean SNAP=${SPOT}/usr/sbin/snap SORT=${SPOT}/usr/bin/sort STARTSRC=${SPOT}/usr/bin/startsrc STARTWPAR=${SPOT}/usr/sbin/startwpar STOPSRC=${SPOT}/usr/bin/stopsrc STOPWPAR=${SPOT}/usr/sbin/stopwpar SYNCWPAR=${SPOT}/usr/sbin/syncwpar SYSDUMPDEV=${SPOT}/usr/bin/sysdumpdev SYNC=${SPOT}/usr/sbin/sync TAIL=${SPOT}/usr/bin/tail TAR=${SPOT}/usr/bin/tar TCTL=${SPOT}/usr/bin/tctl TEE=${SPOT}/usr/bin/tee TOUCH=${SPOT}/usr/bin/touch TR=${SPOT}/usr/bin/tr TUNCHANGE=${SPOT}/usr/sbin/tunchange UMOUNT=${SPOT}/usr/sbin/umount UNAME=${SPOT}/usr/bin/uname VMO=${SPOT}/usr/sbin/vmo WALL=${SPOT}/usr/sbin/wall WC=${SPOT}/usr/bin/wc #---------------------------- AIX file pathnames BOOTPTAB=/etc/bootptab DHCPSD=/etc/dhcpsd.cnf FILESYSTEMS=/etc/filesystems FIRSTBOOT=/etc/firstboot HOSTS=/etc/hosts INETD_CONF=/etc/inetd.conf INITTAB=/etc/inittab IPLROM_SETUP=/usr/lib/boot/iplrom.setup LICENSE_SIG=/var/adm/.license.sig RHOSTS="/.rhosts" SWAPSPACES=/etc/swapspaces TFTPACCESS=/etc/tftpaccess.ctl LOCAL_DOMAIN=/etc/nfs/local_domain #---------------------------- module globals -------------------------------- variable="" value="" access_pnt="" mounts="" mount_opts="" tmp_dirs="" tmp_files="" unmounts="" location="" new_root="" chroot="" undo_on_interrupt="" tape_device_name="" tape_block_size="" instp_err_log="" lppchk_error="" disable_cdumount="" typeset -i lvl_a1 lvl_a2 lvl_a3 lvl_a4 typeset -i lvl_b1 lvl_b2 lvl_b3 lvl_b4 #---------------------------- bname # # NAME: bname # # FUNCTION: do a basename equiv in ksh # # DATA STRUCTURES: # parameters: # 1 - The string to work on... # # RETURNS: (char) # The result of the basename function # #------------------------------------------------------------------------------- function bname { S=$1 S=${S%%+(/)} # remove rightmost /s if any S=${S##*/} # remove path echo $S } #---------------------------- DEBUG -------------------------------- # # NAME: DEBUG # # FUNCTION: # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function DEBUG { typeset tmp="" [[ $# > 0 ]] && print $* read tmp?">>>>>>>>>>>>>>>>>> DEBUG: any key to continue <<<<<<<<<<<<<<<<<<<" } # end of DEBUG #---------------------------- unmount_chroot_libs # # NAME: unmount_chroot_libs # # FUNCTION: # Unmounts a SPOT server's libraries from overmounted subdirectories in # the SPOT. # # parameters: # # global: # location = location of SPOT used to support chroot env. # RETURNS: (int) # 0 = success # #------------------------------------------------------------------------------- function unmount_chroot_libs { mnt_pnt="" found_mnt="" lib="" # Nothing to do if working with a /usr SPOT since we didn't mount # the libraries in the first place. [[ ${location} = /usr ]] && return 0 # Look for the mounted libraries in the mount table. Then look through # the mount list if it appears we need to unmount the libraries. ${MOUNT} | ${EGREP} -q "(${NIM_CHROOT_LIBS1}|${NIM_CHROOT_LIBS2})" if [[ $? -eq 0 ]] then for i in ${mounts} do # separate stanza mnt_pnt=${i##*:} # is this one of the 2 we're looking for? if [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS1} ]] then nim_unmount ${mnt_pnt} force found_mnt=${mnt_pnt} lib=${NIM_CHROOT_LIBS1} elif [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS2} ]] then nim_unmount ${mnt_pnt} force found_mnt=${mnt_pnt} lib=${NIM_CHROOT_LIBS2} fi done fi # If we found a mount point above, unmount the SPOT from the chroot # environment. This may also need force unmounting because we force # unmounted the libraries which were mounted in the SPOT's subdirs. if [[ -n ${found_mnt} ]] then # Get the SPOT mount point by stripping off the end of the # library's mount point (matching the library location in the # chroot environment), then adding /usr back on. mnt_pnt=${found_mnt%%${lib}}/usr nim_unmount ${mnt_pnt} force fi return 0 } #---------------------------- cleanup -------------------------------- # # NAME: cleanup # # FUNCTION: # performs cleanup operations on exit # # EXECUTION ENVIRONMENT: # # NOTES: # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # # OUTPUT: #------------------------------------------------------------------------------- function cleanup { typeset i="" typeset dir_name="" # anything that needs executing? if [[ -s ${TMPDIR}/undo_on_exit ]] then ${CHMOD} +x ${TMPDIR}/undo_on_exit && ${TMPDIR}/undo_on_exit fi # reset the tape block size if necessary if [[ -n "${tape_block_size}" ]] && [[ -n "${tape_device_name}" ]] then ${CHDEV} -l ${tape_device_name} -a block_size=${tape_block_size} \ 1>/dev/null 2>${ERR} || warning_from_cmd ${CHDEV} fi # unmount anything we mounted # First, unmount the server's libraries if we mounted them # -- we may need to force unmount them because for some reason, # processes are accessing the libraries and causing a non-forced # unmount to fail. unmount_chroot_libs # lets attempt to unmount all the mounts now. We should keep trying # until they are all gone. If after about 10 tries then we better # force unmount them. There may be situations where the removal of # directories later will inadvertently remove the wrong files and # directories if this unmount doesn't occur. let unmount_retries=10 while [[ -n ${mounts} ]] && (( unmount_retries > 0 )) do nim_unmount all 2>/dev/null if [[ -n ${mounts} ]] then let unmount_retries=unmount_retries-1 ${SLEEP} 1 fi done [[ -n ${mounts} ]] && nim_unmount all force # do we still require nfs4 mounts? if [[ -s ${TMPDIR}/unmount_on_exit ]] then ${CHMOD} +x ${TMPDIR}/unmount_on_exit && ${TMPDIR}/unmount_on_exit fi # remove tmp files for i in ${tmp_files} do ${RM} ${i} 2>/dev/null done # cd to a neutral directory before removing temporary directories cd /tmp 2>/dev/null # remove tmp dirs for i in ${tmp_dirs} do dir_name=${i%:*} if [[ -d ${dir_name} ]] then protected_dir ${i} || ${RM} -r ${dir_name} 2>/dev/null fi done # remove tmp stuff # for unknown reasons, if "eval" is not used at this point, the shell will # complain about not being able to exeucte "/usr/bin/rm -f" (why?????) eval ${RM} /tmp/_nim_$$.err 2>/dev/null eval ${RM} -r ${TMPDIR} 2>/dev/null unset AUTOMOUNT_DISABLE_FLAG # set by c_instpot when cdromd is running. } # end of cleanup #---------------------------- warning -------------------------------- # # NAME: warning # # FUNCTION: # displays warning messages # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = errno # 2 = str1 of error msg # 3 = str2 of error msg # 4 = str3 of error msg # global: # # RETURNS: (int) # # OUTPUT: #------------------------------------------------------------------------------- function warning { typeset errno=${1:-${ERR_SYS}} tmpwarn=${TMPDIR}/$$.tmp_warn # display the error msg as a warning # prepend a translated "warning" string warn_str=`${C_ERRMSG} ${MSG_WARNING} ${C_ERRMSG_MSG} "" "" "" "" 2>&1` print -n ${warn_str}": " > ${tmpwarn} 2>&1 ${C_ERRMSG} ${1} ${C_ERRMSG_ERR} ${PROGNAME} "${2}" "${3}" "${4}" \ >> ${tmpwarn} 2>&1 # do we need to update the err_info field on a client? if [ "${UPDT_CL_ERR_INFO}" = "yes" ] then ${NIMCLIENT} -o change -aforce=yes -aignore_lock=yes \ -aerr_info="$(cat ${tmpwarn})" else ${CAT} ${tmpwarn} 1>&2 fi ${RM} ${tmpwarn} # check for additional error output from command. if [[ ${errno} = ${ERR_CMD} ]] && [[ -s ${ERR} ]] then # if updating err_info attribute on client, capture the # output and call nimclient to do the update. # otherwise display the output. if [[ "${UPDT_CL_ERR_INFO}" = "yes" ]] then if [[ -n "${instp_err_log}" ]] then # Don't want to add installp output to the # err_info attribute. Add a msg about # viewing the log. err_txt=`${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${instp_err_log}" \ "" "" "" 2>&1` elif [[ -n "${lppchk_error}" ]] then # Don't want to add lppchk output to the # err_info attribute. Add a msg about # viewing the log. err_txt=`${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${LPPCHK_LOG}" \ "" "" "" 2>&1` else # remove any "rc=" that might exist in # the output err_txt=`${AWK} '{gsub(/rc=[0-9]+/,"");print}' \ ${ERR} 2>&1` fi ${NIMCLIENT} -o change -aforce=yes -aignore_lock=yes \ -aerr_info="$( print ${err_txt} )" else # remove any "rc=" that might exist in the output ${AWK} '{gsub(/rc=[0-9]+/,"");print}' ${ERR} 1>&2 fi fi # In some cases, we show output from the failed cmd and don't # capture the err_info in ${ERR}. Let's print a generic msg # about viewing a log. if [[ -n "${lppchk_error}" ]] then ${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${LPPCHK_LOG}" "" "" "" elif [[ "${NIM_SHOW_PROGRESS}" = "yes" ]] && [[ -n "${instp_err_log}" ]] then ${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${instp_err_log}" "" "" "" fi instp_err_log="" } # end of warning #---------------------------- warning_from_cmd -------------------------------- # # NAME: warning_from_cmd # # FUNCTION: # displays error message from failed commands but does NOT exit # # EXECUTION ENVIRONMENT: # # NOTES: # ASSUMES error output from failed commad is in the ${ERR} file # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = name of command which failed # global: # # RETURNS: (int) # # OUTPUT: #------------------------------------------------------------------------------- function warning_from_cmd { # display the error msg warning ${ERR_CMD} "${1}" } # end of warning_from_cmd #---------------------------- error -------------------------------- # # NAME: error # # FUNCTION: # displays the specified error message & exits # # EXECUTION ENVIRONMENT: # # NOTES: # exits with a "1" # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = errno # 2 = str1 of error msg # 3 = str2 of error msg # 4 = str3 of error msg # global: # # RETURNS: (int) # # OUTPUT: #------------------------------------------------------------------------------- function error { typeset errno=${1:-${ERR_SYS}} typeset override_txt=${5} # used when error msg not in catalogue # display the error msg if [[ -n "${override_txt}" ]] && [[ -z "${2}" ]] then err_txt="${override_txt}" else err_txt=`${C_ERRMSG} ${errno} ${C_ERRMSG_ERR} ${PROGNAME} "${2}" "${3}" "${4}" 2>&1` fi # do we need to update the err_info field on a client? if [ "${UPDT_CL_ERR_INFO}" = "yes" ] then ${NIMCLIENT} -o change -aforce=yes -aignore_lock=yes \ -aerr_info="$( print ${err_txt} )" else print "rc=${errno}" 1>&2 print ${err_txt} 1>&2 fi # check for additional error output from command. if [[ ${errno} = ${ERR_CMD} ]] && [[ -s ${ERR} ]] then # if updating err_info attribute on client, capture the # output and call nimclient to do the update. # otherwise display the output. if [[ "${UPDT_CL_ERR_INFO}" = "yes" ]] then if [[ -n "${instp_err_log}" ]] then # Don't want to add installp output to the # err_info attribute. Add a msg about # viewing the log. err_txt=`${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${instp_err_log}" \ "" "" "" 2>&1` elif [[ -n "${lppchk_error}" ]] then # Don't want to add lppchk output to the # err_info attribute. Add a msg about # viewing the log. err_txt=`${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${LPPCHK_LOG}" \ "" "" "" 2>&1` else # remove any "rc=" that might exist in # the output err_txt=`${AWK} '{gsub(/rc=[0-9]+/,"");print}' \ ${ERR} 2>&1` fi ${NIMCLIENT} -o change -aforce=yes -aignore_lock=yes \ -aerr_info="$( print ${err_txt} )" else # remove any "rc=" that might exist in the output ${AWK} '{gsub(/rc=[0-9]+/,"");print}' ${ERR} 1>&2 fi fi # In some cases, we show output from the failed cmd and don't # capture the err_info in ${ERR}. Let's print a generic msg # about viewing a log. if [[ -n "${lppchk_error}" ]] then ${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${LPPCHK_LOG}" "" "" "" elif [[ "${NIM_SHOW_PROGRESS}" = "yes" ]] && [[ -n "${instp_err_log}" ]] then ${C_ERRMSG} ${MSG_SEE_LOG_FILE} \ ${C_ERRMSG_MSG} "${instp_err_log}" "" "" "" fi instp_err_log="" # cd to neutral dir cd /tmp 2>/dev/null # If called from c_cust_lku, then we must # manually update the client state since # c_script isn't being used. if [[ "${CALLED_FROM_NIMCLIENT_LKU}" = "yes" ]] then ${NIMCLIENT} -R failure fi # exit exit ${1} } # end of error #---------------------------- err_from_cmd -------------------------------- # # NAME: err_from_cmd # # FUNCTION: # displays error message from failed commands # # EXECUTION ENVIRONMENT: # # NOTES: # ASSUMES error output from failed commad is in the ${ERR} file # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = name of command which failed # global: # # RETURNS: (int) # # OUTPUT: #------------------------------------------------------------------------------- function err_from_cmd { # display the error msg error ${ERR_CMD} "${1}" } # end of err_from_cmd #---------------------------- err_signal -------------------------------- # # NAME: err_signal # # FUNCTION: # error signal handler # # EXECUTION ENVIRONMENT: # # NOTES: # calls error # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # # OUTPUT: #------------------------------------------------------------------------------- function err_signal { trap "" 1 2 11 15 [[ -n "${undo_on_interrupt}" ]] && ${undo_on_interrupt} error ${ERR_SIGNAL} 1 } # end of err_signal #---------------------------- mk_tmp_dir -------------------------------- # # NAME: mk_tmp_dir # # FUNCTION: # creates a temporary directory for temp files # # EXECUTION ENVIRONMENT: # # NOTES: # # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # # OUTPUT: #------------------------------------------------------------------------------- function mk_tmp_dir { typeset -i retry_count=0 typeset -i retry_max=11 # set umask umask 022 # Note: Process ID's may be re-cycled. So include the string # _nim_dir in the name of the temporary directory. # Use the string _nim_ in file names. # Also, retry 10 time with a name like _nim_dir_$$ before # giving up and re-using _nim_dir_$$. while (( $retry_count < $retry_max )) do if ${MKDIR} ${TMPDIR} 2>/tmp/_nim_$$.err then break else (( retry_count = retry_count + 1 )) if (( $retry_count < $retry_max - 1 )) then TMPDIR=/tmp/_nim_dir${retry_count}_$$ else TMPDIR=/tmp/_nim_dir_$$ ${RM} -r ${TMPDIR} fi fi done } #---------------------------- nim_init -------------------------------- # # NAME: nim_init # # FUNCTION: # initializes the NIM environment for a shell script # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function nim_init { typeset -i tmp_free=0 typeset http_avail="no" # create a dir for tmp files # do this now, before anything else because other functions may be called # which depend on this directory mk_tmp_dir # NIMINFO file must exist # in the network boot environment, /SPOT will always contain the niminfo # file which was tftp'd from the boot server, so look for this version # of the file first if [[ -s /SPOT/niminfo ]] then . /SPOT/niminfo elif [[ -s ${NIMINFO} ]] then # we're not currently executing in the network boot environment # use the version which is in the traditional place . ${NIMINFO} else print "unable to access the ${NIMINFO} file" 1>&2 exit 1 fi # must have at least 5 meg of free space in /tmp tmp_free="$( ${DF} /tmp | ${AWK} 'NR==2{print $3}' 2>/dev/null )" (( ${tmp_free} < ${REQUIRED_TMP_SPACE} )) && \ error ${ERR_SPACE} /tmp ${REQUIRED_TMP_SPACE} ${tmp_free} # check if NFS reserved ports are required for NFS communications # set nfso option accordingly. if [[ "${NFS_RESERVED_PORT}" = "yes" ]] then /usr/sbin/nfso -o nfs_use_reserved_ports=1 >/dev/null elif [[ "${NFS_RESERVED_PORT}" = "no" ]] then /usr/sbin/nfso -o nfs_use_reserved_ports=0 >/dev/null fi # increase ulimit values (reliability enhancement for nim services) if [[ -z ${NIM_BOSINST_ENV} ]] then ulimit -f unlimited >/dev/null 2>&1 ulimit -n 4000 >/dev/null 2>&1 fi # Check /enable http download attempts if [[ "$INUCLIENTS" != yes ]] then http_avail=$( ${NIMCLIENT} -l -l master 2>/dev/null |${AWK} '/http_support/{print $3}') fi export HTTP_SUPPORT=$http_avail # set strict signature policy - if using medium # (unable to process terminal input) if [[ "medium" = "$(LANG=C ${CHSIGNPOLICY} -p 2>/dev/null | ${AWK} '(NR==2){print $1}')" ]] then export INUSIGNPOLICY=high fi # enable snapshot mksysb failover export CALLED_FROM_NIM=y } # end of nim_init #---------------------------- nim_mount -------------------------------- # # NAME: nim_mount # # FUNCTION: # mounts the specified "object" over the specified local mount point; when # no local mount points are specified, this function will create one # "object"s may be on of the following: # 1) local directory # 2) remote directory (in the form of "host:dir") # 3) local CDROM # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = object to mount # 2 = local mount point (optional) # global: # access_pnt = set to local access point # mounts = list of mounts performed by nim_mount # disable_cdumount = if cdrom is already mounted by cdromd, don't cdumount # # RETURNS: (int) # 0 = success; local mount pnt returned via access_pnt # # OUTPUT: #------------------------------------------------------------------------------- MAX_MNT=8 function nim_mount { typeset object=${1} typeset -i i=0 typeset mnt_params="" typeset access_pnt_inode="" typeset automount_flag="" typeset nfs4_access="" typeset nfs4_mount="" typeset nfs4_link="" typeset obj_is_iso="" # NOTE that access_pnt is a global, not a local variable access_pnt=${2:-""} [[ -z "${object}" ]] && return 0 # determine whether or not we're dealing with an iso image if [[ -f "${object}" ]] && \ [[ "${object##*.}" = "iso" ]]; then obj_is_iso="yes" else obj_is_iso="no" fi # check for unnecessary mounts if [[ -z "${access_pnt}" ]] && \ [[ ${object} != /dev/cd[0-9]* ]] && \ [[ ${object} != /dev/usbms[0-9]* ]] && \ [[ ${object} != ?*:?* ]] && \ [[ ${obj_is_iso} = "no" ]] then # object is local directory and no specific mount point requested # therefore, no reason to mount it - return current path access_pnt=${object} return 0 fi # if nfs4 mount, NIM master will start nfsrgyd # and return mount parms if [[ ${object} = ?*:?* ]] then if [[ $NIM_SERVER_TYPE != "linux" ]]; then nfs4_access=`${NIMCLIENT} -m $object` # # The following conditional is added for install from NIMoL # for NFSv4. The client will not be able to execute # 'nimclient -m' so the following code segment will handle # the mount and build up the nfs4_access string. # elif [[ $NIM_SERVER_TYPE = "linux" ]] && [[ -n $NIM_NFS4_MOUNTS ]]; then # example: NIM_NFS4_MOUNTS=" b9rshmc:/:sys:/b9rshmc.sys " NIM_NFS4_HOST=`echo $NIM_NFS4_MOUNTS | $CUT -d: -f1` NIM_NFS4_LOCATION=`echo $NIM_NFS4_MOUNTS | $CUT -d: -f2` NIM_NFS4_SECURITY=`echo $NIM_NFS4_MOUNTS | $CUT -d: -f3` NIM_NFS4_DESTINATION=`echo $NIM_NFS4_MOUNTS | $CUT -d: -f4` $MKDIR -p ${NFS4_MNTDIR}${NIM_NFS4_DESTINATION} ${MOUNT} -vnfs -overs=4,sec=${NIM_NFS4_SECURITY} \ -ohard,intr ${NIM_NFS4_HOST}:${NIM_NFS4_LOCATION} ${NFS4_MNTDIR}${NIM_NFS4_DESTINATION} nfs4_location=`echo $object | $CUT -d: -f2` nfs4_access="${NFS4_MNTDIR}${NIM_NFS4_DESTINATION} ${nfs4_location}" fi if [[ -n "${nfs4_access}" ]] then nfs4_mount=`${ECHO} ${nfs4_access} | ${AWK} '{print $1}'` nfs4_link=`${ECHO} ${nfs4_access} | ${AWK} '{print $2}'` fi fi # Define mount point for nfs3 if [[ -z ${nfs4_access} ]] then # need a local mount point? if [[ -z "${access_pnt}" ]] then # going to create a tmp directory in TMPDIR with a prefix of "mnt" while (( ${i} < ${MAX_MNT} )) do access_pnt=${TMPDIR}/mnt${i} [[ ! -d ${access_pnt} ]] && break let i=i+1 done (( ${i} >= ${MAX_MNT} )) && error ${ERR_GEN_SEQNO} ${TMPDIR}/mnt fi # Define link for nfs4 else # is there a specified link name? if [[ -z "${access_pnt}" ]] then # create a tmp link while (( ${i} < ${MAX_MNT} )) do # build link using nfs4 vars access_pnt="${nfs4_mount}.$$_${i}" [[ ! -h ${access_pnt} ]] && break let i=i+1 done (( ${i} >= ${MAX_MNT} )) && error ${ERR_GEN_SEQNO} ${access_pnt} else # nfs4 access point will be defined as a symlink, so delete dir # NOTE: nim_mount should never be called with a non-empty mount point # otherwise, data will be lost when handling nfs4 mounts ${RM} -r "${access_pnt}" 2>/dev/null fi fi # need to create the local access point? if [[ ! -r ${access_pnt} ]] then # yes - doesn't already exist if [[ -z ${nfs4_access} ]] then ${MKDIR} ${access_pnt} 2>${ERR} || err_from_cmd ${MKDIR} # get the inode of this dir - for adding to remove list. access_pnt_inode=`${LS} -i -d ${access_pnt} 2>/dev/null | ${AWK} '{print ":"$1}'` else ${LN} -fs "${nfs4_mount}${nfs4_link}" ${access_pnt} 2>${ERR} || err_from_cmd ${LN} # get the inode of this link - for adding to remove list. access_pnt_inode=`${LS} -i -N ${access_pnt} 2>/dev/null | ${AWK} '{print ":"$1}'` fi # if access_pnt ends in "/tftpboot", then don't add it to the list of # dirs to be removed # we do this in order to avoid removing the /tftpboot directory in the # inst_root so that clients installed with "source=spot" will get # this directory [[ ${access_pnt##*/} != tftpboot ]] && \ tmp_dirs="${access_pnt}${access_pnt_inode} ${tmp_dirs}" fi # mount the "object" (either local CDROM, USB, remote dir, or local dir) case ${object} in /dev/usbms[0-9]*) USBRFS=`${BOOTINFO} -f ${object}` mnt_params=-rv${USBRFS} ;; /dev/cd[0-9]*) # CDROM # check if the device is manage by the cdromd ${CDCHECK} -aq ${object} 2>/dev/null 1>&2 # If cdromd is running and we chroot to do a spot copy, cdromd will # not be detected in the chroot environment. We use AUTOMOUNT_DISABLE_FLAG to # disable all cd automount calls. # AUTOMOUNT_DISABLE_FLAG is set by c_instspot.c if [[ $? -eq 0 ]] && [[ $AUTOMOUNT_DISABLE_FLAG != "true" ]] then # cdrom is managed by cdromd automount_flag="true" ${CDCHECK} -mq ${object} 2>/dev/null 1>&2 #check if cdrom is mounted if [[ $? -eq 0 ]] then disable_cdumount="true" access_pnt=`${CDCHECK} -mq ${object} 2>/dev/null` else if ${CDMOUNT} -q ${object} 2>${ERR} #mount the cdrom then access_pnt=`${CDCHECK} -mq ${object} 2>/dev/null` # get its mount point else warning_from_cmd ${CDMOUNT} err_from_cmd ${CDMOUNT} fi fi else mnt_params="-r -vcdrfs" fi ;; ?*:?*) # remote dir mnt_params="-ohard,intr -vnfs" ;; *) # local dir or iso image file if [[ "${obj_is_iso}" = yes ]]; then ${LOOPMOUNT} -i "${object}" -m "${access_pnt}" -o "-v cdrfs -o ro" 2> ${ERR} 1>&2 [[ $? -ne 0 ]] && err_from_cmd ${LOOPMOUNT} automount_flag="true" fi ;; esac # nfs4 ? complete : proceed if [[ -n ${nfs4_access} ]] then # define hard link # necessary for determining unmount # of nimclient mount_pnt link_dir="${NFS4_LINKDIR}/${nfs4_mount##*/}" link_file="${link_dir}/linkfile" ${MKDIR} -p ${link_dir} ${TOUCH} ${link_file} ${LINK} ${link_file} "${NFS4_LINKDIR}/${access_pnt##*/}" # create exit script for unmount [[ $? = 0 ]] && \ print "\ncount=\`${LS} -e ${link_file} 2>/dev/null | \ ${AWK} '{print \$2}'\`" >> ${TMPDIR}/unmount_on_exit && \ print "\n(( \$count == 1 )) && ${UNMOUNT} ${nfs4_mount} 2>/dev/null" \ >> ${TMPDIR}/unmount_on_exit elif [[ $automount_flag != "true" ]]; then # cdromd is not running, run the mount command # if mount_opts is set, lets try them # if the mount fails, try removing the mount_opts if ${MOUNT} ${mnt_params} ${mount_opts} ${object} ${access_pnt} 2>${ERR} then : else warning_from_cmd ${MOUNT} ${MOUNT} ${mnt_params} ${object} ${access_pnt} 2>${ERR} || \ err_from_cmd ${MOUNT} fi fi # remember that we've got something mounted # NOTE that we're pushing this onto a stack - it is important that we do # the unmounts in reverse order mounts="${object}:${access_pnt} ${mounts}" } # end of nim_mount #---------------------------- nim_unmount -------------------------------- # # NAME: nim_unmount # # FUNCTION: # unmounts anything which has been mounted by nim_mount # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = either the keyword "all" or local mount pnt # global: # mounts = list of mounts performed by nim_mount # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: #------------------------------------------------------------------------------- function nim_unmount { typeset dir=${1:-all} typeset force=${2} typeset i="" typeset mnt_pnt="" typeset tmp="" # cd to neutral dir if cd /tmp 2>${ERR} then : else warning_from_cmd cd return 1 fi # look for the specified for i in ${mounts} do # separate stanza mnt_pnt=${i##*:} # this the one we're looking for? if [[ ${dir} = ${mnt_pnt} ]] || [[ ${dir} = all ]] then # unmount it, but first perform a sync and an slibclean to make # sure that nothing in the mount is still thought to be busy. ${SYNC} ${SLIBCLEAN} # If unmounting libraries that we set up for a chroot # environment, reset the libpath to make sure that # the mount will succeed. if [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS1} ]] || [[ ${mnt_pnt} = *${NIM_CHROOT_LIBS2} ]] then ${UNSET_CHROOT_LIBPATH} fi # check if the device is manage by the cdromd object=${i%%:*} ${CDCHECK} -aq ${object} 2>/dev/null 1>&2 if [[ $? -eq 0 ]] && [[ $AUTOMOUNT_DISABLE_FLAG != "true" ]] then # cdrom is managed by cdromd ${CDCHECK} -mq ${object} 2>/dev/null 1>&2 # check if cdrom is mounted if [[ $? -eq 0 ]] && [[ $disable_cdumount != "true" ]] then if ! ${CDUMOUNT} ${object} 1> /dev/null 2>${ERR} then warning_from_cmd ${CDUMOUNT} tmp="${i} ${tmp}" fi fi # nfs4 uses links, let's prevent a bogus unmount elif [[ -h ${mnt_pnt} ]] then if ! ${UNLINK} ${mnt_pnt} then warning_from_cmd ${UNMOUNT} tmp="${i} ${tmp}" fi # since multiple access points may link # to an nfs4 server's root mount we need # to check the link count prior to unmount ${RM} "${NFS4_LINKDIR}/${mnt_pnt##*/}" 2>/dev/null # assuming that files are iso images elif [[ -f "${object}" ]]; then if ! ${LOOPUMOUNT} -i "${object}" -m "${mnt_pnt}" 2> ${ERR} 1>&2; then warning_from_cmd ${LOOPUMOUNT} tmp="${i} ${tmp}" fi # process mounted dir - force option elif [[ -n ${force} ]] then # We were told to force unmount this directory. # Try to unmount without the force first. ${UNMOUNT} ${mnt_pnt} > /dev/null 2>&1 if [[ $? -ne 0 ]] then if ! ${UNMOUNT} -f ${mnt_pnt} 1> /dev/null 2>${ERR} then warning_from_cmd ${UNMOUNT} tmp="${i} ${tmp}" fi fi # process mounted dir - normal else if ! ${UNMOUNT} ${mnt_pnt} 2>${ERR} then warning_from_cmd ${UNMOUNT} tmp="${i} ${tmp}" fi fi else # not unmounting this dir - add it back to the list tmp="${i} ${tmp}" fi done # new list reflects the mounts that are still active mounts=${tmp} } # end of nim_unmount #---------------------------- parse_attr_ass -------------------------------- # # NAME: parse_attr_ass # # FUNCTION: # validates command line attribute assignements # # EXECUTION ENVIRONMENT: # # NOTES: # calls error # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function parse_attr_ass { typeset i="" # is it in the correct format (=)? if [[ "${1}" != +(?)=+(?) ]] then error ${ERR_VALUE} "${1}" "valid attribute assignment" fi # separate variable from value # NOTE that we must be careful here as the "value" may have "=" chars in it variable=${1%%=*} value=${1#*=} # make sure its in our list of acceptable attributes for i in ${REQUIRED_ATTRS} do if [[ ${variable} = ${i} ]] then return 0 fi done for i in ${OPTIONAL_ATTRS} do if [[ ${variable} = ${i} ]] then return 0 fi done # not an acceptable attr error ${ERR_CONTEXT} "${variable}" } # end of parse_attr_ass #---------------------------- ck_attrs -------------------------------- # # NAME: ck_attrs # # FUNCTION: # checks for missing attributes # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function ck_attrs { typeset i="" typeset curval="" typeset attr_counted="" typeset -i attr_count=0 for i in ${REQUIRED_ATTRS} do eval curval=\$\{${i}\} if [[ -z "${curval}" ]] then error ${ERR_MISSING_ATTR} ${i} fi done for i in ${EXCLUSIVE_ATTRS} do eval curval=\$\{${i}\} if [[ -n "${curval}" ]] && [[ $attr_count != 0 ]] then error ${ERR_ATTR_CONFLICT} ${i} ${attr_counted} fi if [[ -n "${curval}" ]] then attr_counted=${i} attr_count=1 fi done if [[ -n "${EXCLUSIVE_ATTRS}" ]] && [[ $attr_count != 1 ]] then error ${ERR_MISSING_ATTR} "" fi } # end of ck_attrs #---------------------------- cmd_what -------------------------------- # # NAME: cmd_what # # FUNCTION: # displays the list of required and optional attributes which this method # will accept # # EXECUTION ENVIRONMENT: # # NOTES: # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # REQUIRED_ATTRS # OPTIONAL_ATTRS # # RETURNS: (int) # 0 = success # # OUTPUT: # writes info to stdout #------------------------------------------------------------------------------- function cmd_what { typeset i="" if [[ -n "${REQUIRED_ATTRS}" ]] then print "\nrequired attrs are:" for i in ${REQUIRED_ATTRS} do print "\t${i}" done else print "\nno required attrs" fi if [[ -n "${OPTIONAL_ATTRS}" ]] then print "\noptional attrs are:" for i in ${OPTIONAL_ATTRS} do print "\t${i}" done else print "\nno optional attrs" fi print } # end of cmd_what #---------------------------- ck_inst_root_dirs -------------------------------- # # NAME: ck_inst_root_dirs # # FUNCTION: # ensures that the SPOT's inst_root has a directory entry for the filesystem # where the SPOT resides # this is required by installp because, once we've chroot'd into the # inst_root, installp is going to stat "/", which will be the SPOT's # inst_root at that point - stat will fail if there's no entry for # where we've chroot'd into # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # location = SPOT pathname # new_root = pathname of new root (where we'll chroot to) # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function ck_inst_root_dirs { typeset fs="" # what is the mount point for the filesystem that the SPOT resides in? fs=$(${DF} ${location} 2>/dev/null | ${AWK} 'NR==2{print $7}' 2>/dev/null) [[ -z "${fs}" ]] && error ${ERR_FS_INFO} ${location} # does the directory exist in the new root? if [[ ! -d "${new_root}${fs}" ]] then # create it now ${MKDIR} ${new_root}${fs} 2>${ERR} || err_from_cmd ${MKDIR} fi } # end of ck_inst_root_dirs #---------------------------- setup_chroot_env -------------------------------- # # NAME: setup_chroot_env # # FUNCTION: # mounts the appropriate dirs in order to setup a chroot environment # within a SPOT # this kind of environment is required because we use installp to install # software into a SPOT, but it doesn't understand any pathnames other # than "/" and "/usr" # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = optional; when present, it is the pathname of the # inst_root directory to use # global: # location = SPOT pathname # new_root = pathname of new root (where we'll chroot to) # chroot = command to execute in order to chroot # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function setup_chroot_env { typeset root_sync="" typeset inr="" typeset inr_path="" typeset inr_ln="" typeset spot_fs="" typeset spot_fs_path="" typeset first_dir="" typeset dir_created="" typeset first_dir_inode="" [[ -s /usr/ios/cli/ios.level ]] && return # initialize pathnames for the inst_root directory # this directory will become the root ("/") directory after we chroot if [[ -n "${1}" ]] then root_sync=TRUE inr=${1} inr_path=${inr}${inr%/*} inr_ln=${inr}${inr} else inr="${location}/${INST_ROOT}" inr_path=${inr}/lpp/bos inr_ln=${inr_path}/inst_root fi # initialize pathnames for the SPOT's filesystem which will be created in # the inst_root spot_fs=${location} [[ -n "${spot_fs%/*}" ]] && \ spot_fs_path=${inr}${spot_fs%/*} || \ spot_fs_path="" # make sure SPOT exists [[ ! -d ${location} ]] && error ${ERR_DIR_DNE} spot ${location} [[ ! -d ${location}/${INST_ROOT} ]] && \ error ${ERR_DIR_DNE} inst_root "${location}/${INST_ROOT}" # we use the installp command to install optional software # it only understands the absolute pathnames of / & /usr, so we might have # to setup a choot environment to support the use of installp # is this a non-/usr SPOT or are we going to root-sync a client? if [[ ${location} != /usr ]] || [[ -n "${root_sync}" ]] then # not a /usr SPOT (or a root-sync), so we've got some things to do # we've got to construct an environment which we can chroot into in before # calling installp because installp only knows how to install into # the /usr filesystem new_root=${inr} # make sure no previous mounts have been left dangling ${UNMOUNT} ${new_root}/usr >/dev/null 2>&1 ${UNMOUNT} ${new_root}/tmp >/dev/null 2>&1 ${UNMOUNT} ${new_root}/tftpboot >/dev/null 2>&1 ${UNMOUNT} ${new_root}/images >/dev/null 2>&1 ${UNMOUNT} ${new_root}/opt >/dev/null 2>&1 ${UNMOUNT} ${new_root}/dev >/dev/null 2>&1 ${UNMOUNT} ${new_root}${NIM_CHROOT_LIBS1} >/dev/null 2>&1 ${UNMOUNT} ${new_root}${NIM_CHROOT_LIBS2} >/dev/null 2>&1 # last chance to unmount - check all mounts under inst_root for ir_mount in `${LS} ${new_root}` do ${UNMOUNT} ${new_root}/${ir_mount} >/dev/null 2>&1 done # create subdir in the root which corresponds to the filesystem # where the root resides if [[ ! -d ${inr_path} ]] then first_dir="" ${C_MKDIR} -a location=${inr_path} >${TMPDIR}/first.dir 2>${ERR} || \ err_from_cmd ${C_MKDIR} . ${TMPDIR}/first.dir # get the inode of this directory. This way when we attempt # to remove it later we know we are removing the same directory. first_dir_inode=`${LS} -i -d ${first_dir} 2>/dev/null | ${AWK} '{print ":"$1}'` tmp_dirs="${first_dir}${first_dir_inode} ${tmp_dirs}" fi if [[ ${inr_ln} != / ]] then # make sure no previous links have been left around ${RM} -r ${inr_ln} >/dev/null 2>&1 # create sym link (to fake out the filesystem) ${LN} -s / ${inr_ln} 2>${ERR} || err_from_cmd ${LN} tmp_files="${inr_ln} ${tmp_files}" fi # create subdir in the inst_root which corresponds to the filesystem # where the SPOT resides if [[ -n "${spot_fs_path}" ]] && [[ ! -d ${spot_fs_path} ]] then first_dir="" ${C_MKDIR} -a location=${spot_fs_path} >${TMPDIR}/first.dir \ 2>${ERR} || err_from_cmd ${C_MKDIR} . ${TMPDIR}/first.dir # get the inode of this directory. This way when we attempt # to remove it later we know we are removing the same directory. first_dir_inode=`${LS} -i -d ${first_dir} 2>/dev/null | ${AWK} '{print ":"$1}'` tmp_dirs="${first_dir}${first_dir_inode} ${tmp_dirs}" fi if [[ ${spot_fs} != /usr ]] then # make sure no previous links have been left around ${RM} -r ${inr}${spot_fs} >/dev/null 2>&1 # create sym links (to fake out the filesystem) ${LN} -s / ${inr}${spot_fs} 2>${ERR} || err_from_cmd ${LN} tmp_files="${inr}${spot_fs} ${tmp_files}" fi # mount the SPOT over the new_root /usr directory nim_mount ${location} ${new_root}/usr # mount the server's /tmp over the new_root /tmp directory nim_mount /tmp ${new_root}/tmp # mount the server's /dev over the new_root /dev directory nim_mount /dev ${new_root}/dev # mount /opt over new_root /opt when root_syncing /usr SPOTs if [[ ${spot_fs} = /usr ]] && [[ -d /opt ]]; then nim_mount /opt ${new_root}/opt fi if [[ -z "${root_sync}" ]] then # mount the server's /tftpboot over the new_root /tftpboot directory nim_mount /tftpboot ${new_root}/tftpboot fi # initialize the chroot syntax chroot="${CHROOT} ${new_root}" # For a non-/usr SPOT, always make sure the server's libraries # are available to the chroot'd environment since we'll be # running the server's kernel when processing the SPOT. # Create the mount point for SPOTs that were defined prior # to 4.2.0 if [[ ${location} != /usr ]] then [[ ! -d ${new_root}${NIM_CHROOT_LIBS1} ]] && \ ${MKDIR} -p ${new_root}${NIM_CHROOT_LIBS1} nim_mount /usr/ccs/lib ${new_root}${NIM_CHROOT_LIBS1} [[ ! -d ${new_root}${NIM_CHROOT_LIBS2} ]] && \ ${MKDIR} -p ${new_root}${NIM_CHROOT_LIBS2} nim_mount /usr/lib ${new_root}${NIM_CHROOT_LIBS2} fi else # /usr SPOT new_root="" chroot="" fi } # end of setup_chroot_env #---------------------------- ck_rel_level ------------------------------- # # NAME: ck_rel_level # # FUNCTION: # examines the AIX version/release level of the specified LPP_NAME file # returns 0 if the levels are acceptable to NIM; errors out otherwise # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function ck_rel_level { typeset lpp_name_file=${1} typeset -i ok_version=${2:-${DEFAULT_REQUIRED_VERSION}} typeset -i ok_release=${3:-${DEFAULT_REQUIRED_RELEASE}} # can we read the file? [[ ! -r "${lpp_name_file}" ]] && error ${ERR_FILE_ACCESS} ${lpp_name_file} # parse out the version, release, mod & fix ${AWK} ' /^. . . bos {$/ {found=1;next};\ /^bos.rte .*/ { if (found)\ { split($2,info,".");\ print "version=" info[1];\ print "release=" info[2];\ print "mod=" info[3];\ print "fix=" info[4];\ }\ }' \ ${lpp_name_file} >${TMPDIR}/lpp_info 2>${ERR} || err_from_cmd ${AWK} # include that info in the current environment [[ -s ${TMPDIR}/lpp_info ]] && . ${TMPDIR}/lpp_info # now check the values if (( ${version} < ${ok_version} )) then error ${ERR_RELEASE_LEVEL} ${version} ${release} ${lpp_name_file} elif (( ${ok_release} > 0 )) then if (( ${release} < ${ok_release} )) then error ${ERR_RELEASE_LEVEL} ${version} ${release} ${lpp_name_file} fi fi if [[ -n "${mk_usr_spot}" ]] then # Creating a /usr SPOT so we need to make sure level of bos.rte # on media matches (exactly) that installed in /usr # Get level of bos.rte that's installed... lslppbos=`${LSLPP} -lcIqOu bos.rte 2>${ERR}` || \ err_from_cmd ${LSLPP} vrmf=`echo ${lslppbos} | ${CUT} -d':' -f3` OIFS="$IFS" IFS="." set -- ${vrmf} instver=$1;instrel=$2;instmod=$3;instfix=$4 IFS="$OIFS" if (( ${version} != ${instver} || \ ${release} != ${instrel} || \ ${mod} != ${instmod} || \ ${fix} != ${instfix} )) then # get rid of ugly leading zeros from media vrmf let version=${version} let release=${release} let mod=${mod} let fix=${fix} error ${ERR_USR_SPOT_BOS_MISMATCH} \ "${instver}.${instrel}.${instmod}.${instfix}" \ "${version}.${release}.${mod}.${fix}" fi fi } # end of ck_rel_level #---------------------------- ck_spot_options --------------------------- # # NAME: ck_spot_options # # FUNCTION: # determines whether the specified options are installed into the specified # SPOT # # EXECUTION ENVIRONMENT: # # NOTES: # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = spot pathname # 2 = options to check on # global: # st_applied = value of ST_APPLIED from /usr/include/swvpd.h file # st_committed = value of ST_COMITTED from /usr/include/swvpd.h file # # RETURNS: (int) # 0 = success # 1 = something missing # # OUTPUT: # writes missing options as attr assignments to stdout #------------------------------------------------------------------------------- function ck_spot_options { # make sure st_applied and st_comitted attrs have been supplied [[ -z "${st_applied}" ]] && error $ERR_MISSING_ATTR st_applied [[ -z "${st_committed}" ]] && error $ERR_MISSING_ATTR st_committed typeset spot=${1} typeset optlist=${2} typeset rc=0 typeset i="" typeset state="" typeset database="" # get info out of the /usr product database if ODMDIR=${spot}/lib/objrepos ${ODMGET} product \ >${TMPDIR}/product.usr 2>${ERR} then : else warning_from_cmd "ODMDIR=${spot}/lib/objrepos ${ODMGET} product" return 1 fi # get info out of the /usr/share product database if ODMDIR=${spot}/share/lib/objrepos ${ODMGET} product \ >${TMPDIR}/product.share 2>${ERR} then : else warning_from_cmd "ODMDIR=${spot}/share/lib/objrepos ${ODMGET} product" return 1 fi # for each option required by NIM for a valid SPOT... for i in ${optlist} do # *.all and *.any from the list should never exactly match what # is installed into a spot, so don't bother to check those [[ $i = *.any ]] && continue [[ $i = *.all ]] && continue state="" # which database: usr or share? [[ ${i} = ?*.data ]] && \ database=${TMPDIR}/product.share || \ database=${TMPDIR}/product.usr # is the option installed in the SPOT currently? state=$(${AWK} -v option=${i} '\ $1=="product:"{in_stanza=0;};\ $1=="lpp_name" || $1=="name" {\ field = "\"" option "\"";\ if( ($3==field) || (index($3,option) > 0) )\ in_stanza=1;\ next};\ $1=="state" && in_stanza {print $3; exit}\ ' ${database} 2>/dev/null) # is the state acceptable? if [[ "${state}" != ${st_applied} ]] && [[ "${state}" != ${st_committed} ]] then # either totally missing the option or its in a bad state print "missing=${i}" rc=1 fi done return ${rc} } # end of ck_spot_options #---------------------------- protected_dir -------------------------------- # # NAME: protected_dir # # FUNCTION: # returns SUCCESS (0) is the specified directory is protected from removal # # EXECUTION ENVIRONMENT: # # NOTES: # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = directory to be removed # global: # # RETURNS: (int) # 0 = directory is protected and should NOT be removed # 1 = ok to remove dir # # OUTPUT: #------------------------------------------------------------------------------- function protected_dir { typeset dir=${1} typeset i="" typeset dir_name="" typeset dir_inode="" [[ -z "${dir}" ]] && return 1 dir_name=${dir%:*} dir_inode=${dir#*:} if [[ -n ${dir_inode} ]] && [[ ${dir_inode} != ${dir_name} ]] && [[ ${dir_inode} != `${LS} -i -d ${dir_name} | ${AWK} ' {print $1} '` ]] then return 0 fi for i in ${PROTECTED_DIRS} do [[ ${dir_name} = ${i} ]] && return 0 done # is not protected from removal return 1 } # end of protected_dir #---------------------------- prep_bundle -------------------------------- # # NAME: prep_bundle # # FUNCTION: # prepares environment to use an installp bundle file # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # installp_bundle = pathname of bundle file # bundle_access = local access point for the bundle file # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function prep_bundle { [[ -z "${installp_bundle}" ]] && return 0 bundle_access=${TMPDIR}/bundle rc=1 # local or remote file? if [[ ${installp_bundle} = ?*:/* ]] then # NOTE: As part of the http availability feature - # the initial call will include a check for # web download service.. but not as part of # NIM_BOSINST_ENV condition. if [[ -z ${NIM_BOSINST_ENV} ]] then # Attempt to locate the file # using the nimtthp servicing option # Preference for ssl .. download_srvr=`echo ${installp_bundle} | ${SED} 's/\:.*$//'` download_file=`echo ${installp_bundle} | ${SED} 's/.*://'` download_loc=`echo ${download_file} | ${SED} 's./[^/]*$..'` ${MKDIR} -p ${TMPDIR}/$download_loc ${NIMHTTP} -i $download_srvr -f $download_file -o dest=${TMPDIR} -s >/dev/null 2>&1 || ${NIMHTTP} -i $download_srvr -f $download_file -o dest=${TMPDIR} >/dev/null 2>&1 rc=$? if [[ $rc -eq 0 ]]; then ${MV} ${TMPDIR}/$download_file ${bundle_access} >/dev/null 2>&1 rc=$? fi # end of HTTP fi if [[ $rc -ne 0 ]] then # NFS Method # remote - setup local access nim_mount ${installp_bundle} # copy the bundle into /tmp so installp will have access to it ${CP} ${access_pnt} ${bundle_access} 2>${ERR} || \ err_from_cmd "${CP} ${access_pnt} ${bundle_access}" # unmount nim_unmount ${access_pnt} # end of NFS fi else # already local - just copy it ${CP} ${installp_bundle} ${bundle_access} 2>${ERR} || \ err_from_cmd "${CP} ${installp_bundle} ${bundle_access}" fi } # end of prep_bundle #---------------------------- init_bootlist_attrs ------------------------------ # # NAME: init_bootlist_attrs # # FUNCTION: # formats the global variable "boolist_attrs" based on the settings of the # parameters which are passed in # # EXECUTION ENVIRONMENT: # # NOTES: # the formatting of this information is VERY specific and the man page for # the bootlist command should be consulted BEFORE changing this function # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = client IP address # 2 = BOOTP server IP address # 3 = gateway IP address # 4 = boot filename # global: # bootlist_attrs = boot device list info # # RETURNS: (int) # 0 = bootlist_attrs set # # OUTPUT: #------------------------------------------------------------------------------- function init_bootlist_attrs { typeset client=${1} typeset bserver=${2} typeset gateway=${3:-$bserver} typeset filename=${4} # default is no specific bootlist info bootlist_attrs="" # the syntax for the bootlist command dictates that we can only combine # certain elements of the boot_info # refer to the bootlist man page for futher details if [[ -n "${gateway}" ]] && \ [[ -n "${client}" ]] && \ [[ -n "${bserver}" ]] then # we can specify the gateway info bootlist_attrs="gateway=${gateway} client=${client} bserver=${bserver}" elif [[ -n "${bserver}" ]] then # we may pass bserver alone bootlist_attrs="bserver=${bserver}" fi if [[ -n $filename ]] then bootlist_attrs="$bootlist_attrs filename=$filename" fi } # end of init_bootlist_attrs #---------------------------- ck_installp_flags -------------------------------- # # NAME: ck_installp_flags # # FUNCTION: # makes sure that there is a "-" in front of all installp_flags # any missing "-" are added # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = the installp_flags to check # global: # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: # writes the installp_flags which should be used to stdout #------------------------------------------------------------------------------- function ck_installp_flags { typeset flags=${1:-${DEFAULT_INSTALLP_FLAGS}} typeset new_flags="" # make sure "-" is in front of all installp_flags new_flags=$( echo ${flags} | ${AWK} '{ for(i=1;i<=NF;i++) \ { if (! match($i,/^-.+/) ) \ printf( "-" ); \ print $i \ } }' 2>/dev/null ) echo ${new_flags:-${flags}} } # end of ck_installp_flags #---------------------------- ck_gencopy_flags -------------------------------- # # NAME: ck_gencopy_flags # # FUNCTION: # makes sure that there is a "-" in front of all gencopy_flags # any missing "-"'s are added. # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 = the gencopy_flags to check # global: # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: # writes the gencopy_flags which should be used to stdout #------------------------------------------------------------------------------- function ck_gencopy_flags { typeset flags=${1:-${DEFAULT_GENCOPY_FLAGS}} typeset new_flags="" # make sure "-" is in front of all gencopy_flags new_flags=$( echo ${flags} | ${AWK} '{ for(i=1;i<=NF;i++) \ { if (! match($i,/^-.+/) ) \ printf( "-" ); \ print $i \ } }' 2>/dev/null ) echo ${new_flags:-${flags}} } # end of ck_gencopy_flags #---------------------------- prep_updt_all_lst ----------------------------- # # NAME: prep_updt_all_lst # # FUNCTION: # generates a list of fileset updates on the media which match # installed filesets on the target (SPOT or client) # # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # When the target is either a SPOT that is at a level greater # than or equal to 4.3.0 or any client, this function will use # the "sm_inst" command to generate the list of filesets # needing updateing. # If the target SPOT is less than 4.3.0 then the following # occurs: # uses lslpp to generate list of installed filesets # uses "installp -L" to generate media list # uses awk to match the two lists -- matches take v.r.m.f of # installed filesets into account # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # target_type = type of target "spot" or "client" # lpp_source = installation media # prep_updts = flag variable # global: # fileset_list = file containing list generated by this routine # # RETURNS: (int) # 0 = success if no errors, else errors off # # OUTPUT: # fileset_list contains list of updates to install #------------------------------------------------------------------------------- function prep_updt_all_lst { target_type=${1} lpp_source=${2} prep_updts=${3} lslpp_cmd=${LSLPP} instp_cmd=${INSTALLP} fileset_list=${TMPDIR}/updt_all.lst #initialize some temp files > ${TMPDIR}/up_all.instld > ${TMPDIR}/up_all.media #initialize global "out-list" > ${fileset_list} if [[ ${target_type} = "client" ]] then # target is a client, so use "sm_inst -L" ${SM_INST} installp_cmd -L ${lpp_source} -f _update_all \ 1>${fileset_list} 2>${ERR} #outta here if nothing to work with or errors [ ! -s ${fileset_list} ] || [ -s "${ERR}" ] && \ err_from_cmd ${SM_INST} else # target is a SPOT # augment lslpp cmd lslpp_cmd="${chroot} ${LSLPP}" # Older versions of the "sm_inst" shell script will not have # the support for the "-L" option, therefore the level of the # bos.sysmgt.smit fileset in the SPOT is checked. # If ver.rel >= 4.3 then use "sm_inst -L" # Get the version and release of the bos.sysmgt.smit fileset in # the SPOT vrmf=$( ${lslpp_cmd} -l bos.sysmgt.smit | ${AWK} '/smit/ {print $2}') integer ver=${vrmf%%.*} strrel=${vrmf#*.} integer rel=${strrel%%.*} if (( (ver > 4) || (ver == 4 && (rel > 2)) )) then # target is a SPOT that is at a level >= 4.3. Use "sm_inst -L ". sm_inst_cmd="${chroot} ${SM_INST}" ${sm_inst_cmd} installp_cmd -L ${lpp_source} -f _update_all \ 1>${fileset_list} 2>${ERR} if [[ ${prep_updts} = "yes" ]] then : else #outta here if nothing to work with or errors [ ! -s ${fileset_list} ] && exit 0 [ -s "${ERR}" ] && err_from_cmd ${SM_INST} fi else # Use old method #list the installed filesets capturing name and level ${lslpp_cmd} -qLc | \ ${AWK} 'BEGIN { FS=":" } {printf ("%s %s\n", $2, $3)}' | \ ${SORT} -A -u 1> ${TMPDIR}/up_all.instld 2>${ERR} #outta here if nothing to work with or errors [ ! -s ${TMPDIR}/up_all.instld ] || [ -s "${ERR}" ] && \ err_from_cmd ${LSLPP} #augment installp cmd depending upon caller instp_cmd="${chroot} ${INSTALLP}" #list the contents of the installation media ${instp_cmd} -qL ${lpp_source} 1>${TMPDIR}/up_all.media 2>${ERR} #outta here if nothing to work with or errors [ ! -s ${TMPDIR}/up_all.media ] || [ -s "${ERR}" ] && \ err_from_cmd ${INSTALLP} #loop on the list of installed filesets # -- grep the media listing for matches on that name. # -- awk the resultant list looking for filesets with # greater level than that which is installed. print them. # accumulate output in ${fileset_list} file. while read fs_name level do ${FGREP} ${fs_name} ${TMPDIR}/up_all.media \ > ${TMPDIR}/up_all.grep 2>&1 [ $? -eq 0 ] && \ ${AWK} -v name=${fs_name} -v lev=${level} 'BEGIN { FS=":" split(lev, inst_lev, ".") } { # check for exact match for name, since the # grep may have pulled in supersets of the # name being grepped for. if ($2 == name) { split($3, updt_lev, ".") v3ptfid=$4 # Compare the VRMF of the installed # with the update of each fileset for ( i = 1; i < 5 ; i++ ) { if ( updt_lev[i] > inst_lev[i] ) # Yes this is a newer update if (v3ptfid != "" ) printf ( "%s %s.%s\n", $2, $3, v3ptfid) else printf ( "%s %s\n", $2, $3) else if ( updt_lev[i] == inst_lev[i] ) { # Still need to compare... if (( i == 4 ) && (v3ptfid != "" ) ) printf ( "%s %s.%s\n", $2, $3, v3ptfid) } else # Not a newer update. break } } }' ${TMPDIR}/up_all.grep >> ${fileset_list} done < ${TMPDIR}/up_all.instld ${RM} ${TMPDIR}/up_all.instld > /dev/null 2>&1 ${RM} ${TMPDIR}/up_all.media > /dev/null 2>&1 fi fi } # end of prep_updt_all_lst #---------------------------- prep_instfix_lst --------------------------- # # NAME: prep_instfix_lst # # FUNCTION: # generates a list of fileset updates from a list (string) # of keywords or file containing keywords. # # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure. # calls instfix command to generate list of filesets. # if non-zero returned from instfix, errors off # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # target_type = type of target ("spot" or "client") # fix_type = type of fixes specified ("fixes" list or "bun" # fixes = list of fixes or bundle name # global: # fileset_list = file containing list generated by this routine # # RETURNS: (int) # 0 = success if ok, else errors off. # # OUTPUT: # fileset_list contains list of filesets matching fix keys input #------------------------------------------------------------------------------- function prep_instfix_lst { target_type=${1} fix_type=${2} fixes=${3} lpp_src=${4} instfix_cmd=${INSTFIX} fileset_list=${TMPDIR}/fsets.frm.fixes.lst fileset_errs=${TMPDIR}/fsets.frm.fixes.err #augment instfix cmd depending upon caller [ ${target_type} = "spot" ] && instfix_cmd="${chroot} ${INSTFIX}" #initialize global "out-list" > ${fileset_list} #generate the list from instfix if [ ${fix_type} = "fixes" ] then # use string of fix keywords ${instfix_cmd} -p -k "${fixes}" ${lpp_src} >${fileset_list} 2>${fileset_errs} else # use fix bundle ${instfix_cmd} -p -f ${fixes} ${lpp_src} >${fileset_list} 2>${fileset_errs} fi #NOTE: if instfix encounters errors with *any* of the fixes in # a list, it returns non-zero. # So, we need to re-capture the errors and proceed accordingly. if [ -s ${fileset_errs} ] then ${CAT} ${fileset_errs} > ${ERR} 2>&1 err_from_cmd ${INSTFIX} fi } # end of prep_instfix_lst #---------------------------- check_access # # NAME: check_access # # FUNCTION: # Make sure that client allows the server nimsh (or .rhosts) access # # RETURNS: (int) # 0 = success # 1 = no access # #------------------------------------------------------------------------------- function check_access { client=$1 ${C_RSH} ${client} "\"${ECHO} >/dev/null\"" 2>/dev/null if [ $? -ne 0 ] then # which service was used for remote access? [[ -z ${nim_name} ]] && connect="shell" || connect=`$LSNIM -a connect ${nim_name} 2>/dev/null | $AWK -F"=" '(NR==2) {print $2}'` if [[ ${connect} = *shell* ]]; then thishost=`/usr/bin/hostname` error ${ERR_NO_RHOST} ${client} ${thishost} else error ${ERR_NIMSH_CANNOT_CONNECT} ${client} fi fi return 0 } #---------------------------- check_push_ok # # NAME: check_push_ok # # FUNCTION: # Make sure that target allows the master to perform push operations # 'Target' may not actually be a NIM client. # # RETURNS: (int) # 0 = success # 1 = no access # #------------------------------------------------------------------------------- function check_push_ok { client=$1 check_access ${client} nimpush_ok=`${C_RSH} ${client} "\"/usr/bin/test -f /etc/nimstop && print 0 || print 1\""` [ $nimpush_ok -eq 0 ] && {\ error ${ERR_NO_PUSH} ${client} ${client} } return 0 } #---------------------------- check_cpush_ok # # NAME: check_cpush_ok # # FUNCTION: # Make sure that target allows the master to perform push operations # AND that the target appears to have the NIM client fileset installed # # # RETURNS: (int) # 0 = success # 1 = no access # #------------------------------------------------------------------------------- function check_cpush_ok { client=$1 check_access ${client} nimpush_ok=`${C_RSH} ${client} "\"/usr/bin/test -f /usr/lpp/bos.sysmgt/nim/methods/c_nimpush && print 0 || print 1\""` [ $nimpush_ok -ne 0 ] && {\ error ${ERR_NO_PUSH} ${client} ${client} } return 0 } #---------------------------- get_fileset_level # # NAME: get_fileset_level # # FUNCTION: # Gets the level of the fileset indicated by $1 # # # RETURNS: (int) # 0 = success # 1 = no access # #------------------------------------------------------------------------------- function get_fileset_level { lslpp_fileset=`${LSLPP} -lqcOu ${1}` || \ err_from_cmd "${LSLPP} -lqcOu ${1}" vrmf=`echo $lslpp_fileset | ${CUT} -d":" -f3` version=`echo ${vrmf} | ${CUT} -d"." -f1` release=`echo ${vrmf} | ${CUT} -d"." -f2` mod=`echo ${vrmf} | ${CUT} -d"." -f3` fix=`echo ${vrmf} | ${CUT} -d"." -f4` return 0 } #---------------------------- set_option_lists -------------------------------- # # NAME: set_option_lists # # FUNCTION: Calls c_getlevel to determine the level of AIX that will # supported by the lpp_source. The "SIMAGES_OPTIONS", "REQUIRED_SIMAGES" # and "DEFAULT_SPOT_OPTIONS" variables will be set to include the lists of # appropriate filesets for the level determined. # # EXECUTION ENVIRONMENT: # # NOTES: # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: 1 - the type of source containing the bos image # 2 - the location of the source for the bos image # 3 - the architecture type for support images # # global: version - set by c_getlevel # release - set by c_getlevel # SIMAGES_OPTIONS - set in this routine # REQUIRED_SIMAGES - set in this routine # DEFAULT_SPOT_OPTIONS - set in this routine # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: #------------------------------------------------------------------------------- function set_option_lists { typeset arch=${3} # Call c_getlevel to get the level of the "source". # If the "location" does not contain a bos image, then the # level will come from the level of the NIM client fileset that # is installed. ${C_GETLEVEL} -a type=${1} -a source=${2} \ > ${TMPDIR}/__src_level.$$ # include the level in the current environment. . ${TMPDIR}/__src_level.$$ LPP_SOURCE_LEVEL=${version}${release} # what type of images are needed? LPP_ARCH_TYPE=${arch:=`get_mac_arch`} # Update the default lists to match the level of the install # media if necessary. # NOTE: SIMAGES_OPTIONS_GRAPHICS needs adding to the list # if/when graphics bundles change per release if [[ ${LPP_SOURCE_LEVEL} = 41 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_41 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_41 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_41 SIMAGES_OPTIONS_GRAPHICS= elif [[ ${LPP_SOURCE_LEVEL} = 42 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_42 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_42 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_42 SIMAGES_OPTIONS_GRAPHICS= elif [[ ${LPP_SOURCE_LEVEL} = 43 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_43 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_43 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_43 SIMAGES_OPTIONS_GRAPHICS= elif [[ ${LPP_SOURCE_LEVEL} = 50 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_50 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_50 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_50 SIMAGES_OPTIONS_RPMS=$SIMAGES_OPTIONS_RPMS_50 SIMAGES_OPTIONS_GRAPHICS= elif [[ ${LPP_SOURCE_LEVEL} = 51 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_51 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_51 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_51 SIMAGES_OPTIONS_RPMS=$SIMAGES_OPTIONS_RPMS_51 SIMAGES_OPTIONS_GRAPHICS= elif [[ ${LPP_SOURCE_LEVEL} = 52 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_52 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_52 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_52 SIMAGES_OPTIONS_RPMS=$SIMAGES_OPTIONS_RPMS_52 SIMAGES_OPTIONS_GRAPHICS=$SIMAGES_OPTIONS_GRAPHICS_52 elif [[ ${LPP_SOURCE_LEVEL} = 53 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_53 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_53 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_53 SIMAGES_OPTIONS_RPMS=$SIMAGES_OPTIONS_RPMS_53 SIMAGES_OPTIONS_GRAPHICS=$SIMAGES_OPTIONS_GRAPHICS_53 elif [[ ${LPP_SOURCE_LEVEL} = 61 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_61 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_61 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_61 SIMAGES_OPTIONS_RPMS=$SIMAGES_OPTIONS_RPMS_61 SIMAGES_OPTIONS_GRAPHICS=$SIMAGES_OPTIONS_GRAPHICS_61 elif [[ ${LPP_SOURCE_LEVEL} = 71 ]] then SIMAGES_OPTIONS=$SIMAGES_OPTIONS_71 REQUIRED_SIMAGES=$REQUIRED_SIMAGES_71 DEFAULT_SPOT_OPTIONS=$DEFAULT_SPOT_OPTIONS_71 SIMAGES_OPTIONS_RPMS=$SIMAGES_OPTIONS_RPMS_71 SIMAGES_OPTIONS_GRAPHICS=$SIMAGES_OPTIONS_GRAPHICS_71 fi } #---------------------------- get_oparg_values ------------------------------- # # NAME: get_oparg_values # # FUNCTION: Get the values of the attributes stored in the # opargs hidden attribute for a Custom Task. # # EXECUTION ENVIRONMENT: # # NOTES: For the resource group below, the following global # assignments will be made by this function: # # source=spot filesets="bos.diag" # # The source and filesets variables must be defined in # the calling function. # # bos_inst: # class = groups # type = res_group # operation = bos_inst # opargs = -a source=spot -a filesets="bos.diag" # member1 = 42Gimages # member2 = 42Gspot # # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 - The name of the resource group. # global: # See NOTES. # # RETURNS: NONE # # OUTPUT: NONE #------------------------------------------------------------------------------- function get_oparg_values { RES_GRP_NAME=${1} OPARGS="" # get the opargs hidden attribute OPARGS=`/usr/sbin/lsnim -lF ${RES_GRP_NAME} | ${GREP} opargs | \ ${AWK} 'BEGIN { FS="= " } {print $2}'` OPARGS="${OPARGS}" # Loop through the attributes contained # in the opargs attribute. IFS=" " for i in ${OPARGS} do # Skip -a flag preceding each attribute assignment. if [[ "${i}" = "-a" ]] then variable="" value="" continue fi # No special processing for this attribute. # Just get the attribute type. if [[ "${variable}" != "filesets" ]] && [[ "${variable}" != "fixes" ]] then variable=${i%%=*} fi # If this is the filesets or fixes attribute # be prepared for more than one value. if [[ "${variable}" = "filesets" ]] || [[ "${variable}" = "fixes" ]] then if [[ "${i}" = *=* ]] then value=`${ECHO} ${i} | ${AWK} 'BEGIN { FS="=" } {print $2}'` else value="${value} ${i}" fi eval ${variable}=${value} continue else value=${i#*=} fi # Assign the attribute value to it's attribute type. eval ${variable}=${value} done } #---------------------------- get_res_values -------------------------------- # # NAME: get_res_values # # FUNCTION: Get the members of a resource group and assign # their resource types to their respective values. # # EXECUTION ENVIRONMENT: # # NOTES: For the resource group below, the following global # assigments will be made by this function: # # lpp_source=42Gimages spot=42Gspot # # The lpp_source and spot variables must be defined in # the calling function. # # bos_inst: # class = groups # type = res_group # member1 = 42Gimages # member2 = 42Gspot # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # 1 - The name of the resource group. # global: # See NOTES. # # RETURNS: NONE # # OUTPUT: NONE #------------------------------------------------------------------------------- function get_res_values { RES_GRP_NAME=${1} # Loop through the members of this resource group. /usr/sbin/lsnim -lF ${RES_GRP_NAME} | ${GREP} member | while read member do value=${member#*= } # Get member's resource type. variable=`/usr/sbin/lsnim -l ${value} | ${GREP} type | ${AWK} 'BEGIN { FS="= " } \ {print $2}'` # Assign the resource name to it's type. eval ${variable}=\"${value}\" done } #---------------------------- match_ifs -------------------------------- # # NAME: match_ifs # # FUNCTION: Prints the hostname associated with an interface on a # server that can be reached by a client. # # EXECUTION ENVIRONMENT: # # NOTES: # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: 1 - the name of the client # 2 - the name of the server # # RETURNS: (int) # 0 = success # # OUTPUT: prints the hostname of a machine interface. #------------------------------------------------------------------------------- function match_ifs { client_name=$1 server_name=$2 # Get the server hostname to use by default if all the checks fail. default_server_hostname=`/usr/sbin/lsnim -a if1 $server_name | \ ${AWK} '{if (NR!=1) print $4}'` # # Check 1: Do the client and server both have an interface on # the same network? # # Get the network that the client's primary interface is on. # The client will mount resources from its primary interface. client_network=`/usr/sbin/lsnim -a if1 $client_name | ${AWK} '{if (NR!=1) print $3}'` # Check to see if one of the server interfaces is on the # same network as the client's primary interface. If so, print # the hostname associated with that server interface. if_hostname=`/usr/sbin/lsnim -a if $server_name | ${AWK} '{if (NR!=1) print}' | \ ${AWK} '{if ($3 == netname) print $4}' netname=$client_network` if [[ -n $if_hostname ]] then print $if_hostname return 0 fi # # Check 2: Does the client's network have a default route defined? # # Get the list of networks that the client can access. client_access_nets=`/usr/sbin/lsnim -a routing $client_network | \ ${AWK} '{if (NR!=1) print $3}'` # If the client's network has a default route, then it should be # able to use any interface on the server. for access_net in $client_access_nets do if [[ $access_net = "default" ]] then print ${default_server_hostname} return 0 fi done # # Check 3: Does the client's network have a static route set up to # the server's network? # # Go through the list of server interfaces. If one of the # interfaces is on a network that the client has access to, # then print the hostname associated with that interface. server_ifs=`/usr/sbin/lsnim -a if $server_name | ${AWK} '{if (NR!=1) print $1}'` for check_if in $server_ifs do if_info=`/usr/sbin/lsnim -a $check_if $server_name | ${AWK} '{if (NR!=1) print }'` if_network=`echo $if_info | ${AWK} '{ print $3 }'` if_hostname=`echo $if_info | ${AWK} '{ print $4 }'` for access_net in $client_access_nets do if [[ $if_network = $access_net ]] then print $if_hostname return 0 fi done done # # Check 4: Nothing left to check. Just use the hostname of the # server's primary interface. # # The client does not have a known route to the server. For NIM # operations this could be a problem, but for the purposes of this # routine, we will just print the hostname of the server's primary # interface. print ${default_server_hostname} return 0 } #---------------------------- get_mac_arch # # NAME: get_mac_arch # # FUNCTION: # Determine the machines architecture from the data returned by the # bootinfo command. # # # RETURNS: (int) # 0 = success # # OUTPUT: prints arch type of the client machine. # ia64 = value if bootinfo returns ia64 # power = value if bootinfo returns anything other than ia64 # #------------------------------------------------------------------------------- function get_mac_arch { typeset mac_plat="" mac_plat=`${BOOTINFO} -a 2>/dev/null` convert_arch_value ${mac_plat} return 0 } #---------------------------- convert_arch_value ------------------------------- # # NAME: convert_arch_value # # FUNCTION: # Converts the value in arch_type to a value that NIM expects # # # RETURNS: (int) # 0 = success # # OUTPUT: prints arch type of the client machine. # ia64 = value if parameter is 4|I|ia64 # power = value if parameter is other than 4|I|ia64 # #------------------------------------------------------------------------------- function convert_arch_value { if [[ $1 = @(4|"I"|"ia64") ]] then print "ia64" else print "power" fi return 0 } #---------------------------- get_platform_value ------------------------------- # # NAME: get_platform_value # # FUNCTION: # Converts the integer value of arch_type to a string # # # RETURNS: (int) # 0 = success # # OUTPUT: prints arch type of the client machine. # rs6k = value if parameter is 1 # rspc = value if parameter is 2 # chrp = value if parameter is 3 # ia64 = value if parameter is 4 # #------------------------------------------------------------------------------- function get_platform_value { case $1 in 1) print "rs6k" ;; 2) print "rspc" ;; 3) print "chrp" ;; 4) print "ia64" ;; esac return 0 } #---------------------------- set_geninst ------------------------------- # # NAME: set_geninst # # FUNCTION: # Performs vrmf and flags checks to determine if geninstall command # should be set for usage. # # # RETURNS: (int) # 0 = success # # OUTPUT: returns geninstall or NULL string value # #------------------------------------------------------------------------------- function set_geninst { # before anything, see if we want geninstall [[ -z ${GENINSTALL} ]] && return 0 R_FLAG="" c_FLAG="" a_FLAG="" r_FLAG="" C_FLAG="" s_FLAG="" u_FLAG="" p_FLAG="" U_FLAG="" P_FLAG="" while getopts :R:acrCsup inst_flags do case $inst_flags in R) R_FLAG="-R";; a) a_FLAG="-a";; c) c_FLAG="-c";; r) r_FLAG="-r";; C) C_FLAG="-C";; s) s_FLAG="-s";; u) u_FLAG="-u";; p) p_FLAG="-p";; esac done #don't call geninstall for Cleanup, Listing applied s/w updates, #commit (c) or reject (r) unless (a) is also there if ( [[ ${c_FLAG} != *c* ]] || [[ ${a_FLAG} = *a* ]] ) && [[ ${r_FLAG} != *r* ]] \ && [[ ${C_FLAG} != *C* ]] && [[ ${s_FLAG} != *s* ]] then # get version/release values get_fileset_level bos.rte.install # if version > 5.0, call GENINSTALL command if (( ${version} > 4 )) then # if GENINSTALL is set, and "-u" flag is passed, # then pass flag to geninstall command [[ -n ${GENINSTALL} ]] && [[ ${u_FLAG} = *u* ]] && \ U_FLAG="-u" # if GENINSTALL is set, and "-p" flag is passed, # then pass flag to geninstall command [[ -n ${GENINSTALL} ]] && [[ ${p_FLAG} = *p* ]] && \ P_FLAG="-p" # set geninstall/gencopy variables for use geninstall_cmd="${GENINSTALL} ${U_FLAG} ${P_FLAG} " gencopy_cmd="${GENCOPY} " fi fi return 0 } #----------------------------------------------------------------------------- # # Name: get_level # # Function: Gets the level of the installed NIM master fileset and the # level of the backup. Breaks the levels into integers for # comparison. lvl_a1-lvl_a4 will represent the installed NIM level. # lvl_b1-lvl_b4 will represent the level of the backup. # # Parameters: nim db file # # Returns: Nothing. # #----------------------------------------------------------------------------- function get_level { typeset nimdbfile=$1 typeset INST_LEVEL typeset BACKUP_LEVEL # Problem if INST_LEVEL < BACKUP_LEVEL INST_LEVEL=`${LSLPP} -L bos.sysmgt.nim.master | ${GREP} master | ${AWK} '{print $2}'` cd /tmp ${TAR} -xf $nimdbfile ./etc/NIM.level if [[ $? -ne 0 ]] then ${DSPMSG} -s ${ERR_SET} cmdnim.cat ${ERR_NO_VALID_ENTRIES} '0042-223 %s: Invalid input file: %s\nThe file either cannot be read, is empty, or contains no\nvalid entries.\n' ${PROGRAM_NAME} $nimdbfile exit -1 fi BACKUP_LEVEL=`${CAT} /tmp/etc/NIM.level` lvl_a1=`${ECHO} $INST_LEVEL | ${AWK} 'BEGIN { FS="." } {print $1}'` lvl_a2=`${ECHO} $INST_LEVEL | ${AWK} 'BEGIN { FS="." } {print $2}'` lvl_a3=`${ECHO} $INST_LEVEL | ${AWK} 'BEGIN { FS="." } {print $3}'` lvl_a4=`${ECHO} $INST_LEVEL | ${AWK} 'BEGIN { FS="." } {print $4}'` lvl_b1=`${ECHO} $BACKUP_LEVEL | ${AWK} 'BEGIN { FS="." } {print $1}'` lvl_b2=`${ECHO} $BACKUP_LEVEL | ${AWK} 'BEGIN { FS="." } {print $2}'` lvl_b3=`${ECHO} $BACKUP_LEVEL | ${AWK} 'BEGIN { FS="." } {print $3}'` lvl_b4=`${ECHO} $BACKUP_LEVEL | ${AWK} 'BEGIN { FS="." } {print $4}'` return } #----------------------------------------------------------------------------- # # Name: check_level # # Function: Compares the values set by get_level() to determine whether # or not the installed NIM level (lvl_a1-a4) is at the same level # or higher as the backup (lvl_b1-lvl_b4). # # Parameters: None. Uses the global values lvl_a1-lvl_a4 and lvl_b1-lvl_b4 # # Returns: 0 - The installed NIM level is at the same level as the # backup or higher. # 1 - The backup is at a higher level than the installed # NIM master fileset. # #----------------------------------------------------------------------------- function _check_level { # # Compare the version. # If the master version is less than the backup version, then immediately # return failure. If the master version is greater than the backup version, # then immediately return success. Otherwise, continue checking the other # parts of the v.r.m.f. # if [[ $lvl_a1 -lt $lvl_b1 ]] then return 1 elif [[ $lvl_a1 -gt $lvl_b1 ]] then return 0 fi # # Compare the release. # if [[ $lvl_a2 -lt $lvl_b2 ]] then return 1 elif [[ $lvl_a2 -gt $lvl_b2 ]] then return 0 fi # # Compare the maintenance level. # if [[ $lvl_a3 -lt $lvl_b3 ]] then return 1 elif [[ $lvl_a3 -gt $lvl_b3 ]] then return 0 fi # # Compare the fix level. # if [[ $lvl_a4 -lt $lvl_b4 ]] then return 1 else return 0 fi } function check_level { typeset rc=0 _check_level || rc=$? if [[ $rc -ne 0 ]]; then # reports levels only if do not match print ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_MASTER_LEVEL} \ 'The level of the NIM master fileset on this machine is: %s\n' \ "${lvl_a1}.${lvl_a2}.${lvl_a3}.${lvl_a4}" ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_BACKUP_LEVEL} \ 'The level of the NIM database backup is: %s\n' \ "${lvl_b1}.${lvl_b2}.${lvl_b3}.${lvl_b4}" print fi return $rc } #---------------------------- mget_http_content ------------------------------- # # NAME: mget_http_content # # FUNCTION: # Performs an iterative download of http content from nimhttp service. # The list of download content is obtained from the CWD/.content file. # # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: none (caller must check $?) # #------------------------------------------------------------------------------- function mget_http_content { typeset dir_name=${1%/} typeset reloc_name=${2:+"${2%/}/"} typeset host= typeset fs_name= typeset -i space_need=0 typeset -i free_space=0 # parse out host:dir_name if [[ ${dir_name} = ?*:?* ]]; then host=`echo $dir_name | $CUT -d: -f1` dir_name=`echo $dir_name | $CUT -d: -f2` fi # get the actual fs name fs_name="$( $DF ${reloc_name}${dir_name} | $AWK 'NR==2{print $7}' 2>/dev/null )" # calculate the space needs using the .content file if [[ -n "${reloc_name}${dir_name}/.content" ]] then for i in `$CAT ${reloc_name}${dir_name}/.content | $AWK '{print $5}'` do let space_need=`expr $space_need + $i 2>/dev/null` done fi # check the fs space if (( space_need > 0 )) then let space_need=`expr $space_need / 512 2>/dev/null` free_space="$( $DF ${fs_name} | $AWK 'NR==2{print $3}' 2>/dev/null )" # (attempt to) expand filesystem using 512-byte/block if (( free_space < space_need )); then $CHFS -a size=+$(( space_need - free_space )) ${fs_name} >/dev/null 2>&1 fi fi # determine the type of nimhttp service call if [[ -z $web_client ]] then $NIMHTTP -s ${host:+"-i${host}"} -odest="/tmp/._nimhttp_test_$$" >/dev/null 2>&1 \ && web_client="$NIMHTTP -s" \ || web_client="$NIMHTTP" ${RM} -r /tmp/._nimhttp_test_$$ >/dev/null 2>&1 fi # begin the download attempts - exit on failure if [[ -n "${reloc_name}${dir_name}/.content" ]] then typeset -i bg_job=0 # first pass - download data for entry in `$CAT ${reloc_name}${dir_name}/.content | $AWK '{ if ($1=="DIR:") printf("%s//|%s_%s ",$2,$3,$4); if ($1=="FILE:") printf("%s/|%s_%s ",$2,$3,$4) }'` do entry_name= entry_ownr= entry_mode= [[ -z $entry ]] && continue entry_name=`echo ${entry} | ${SED} 's/\/|.*$//'` entry_ownr=`echo ${entry} | ${SED} 's/.*\/|//'` entry_mode=`echo ${entry_ownr} | ${SED} 's/.*_//'` entry_ownr=`echo ${entry_ownr} | ${SED} 's/\_.*$//'` if (( bg_job < 1 )) then ( $web_client ${host:+"-i${host}"} -f ${dir_name%/}/${entry_name} \ ${reloc_name:+"-odest=${reloc_name%/}"} 2>/dev/null || \ return 1 [[ -n $entry_mode ]] && \ $CHMOD $entry_mode ${reloc_name}${dir_name%/}/${entry_name} 2>/dev/null [[ -n $entry_ownr ]] && \ $CHOWN $entry_ownr ${reloc_name}${dir_name%/}/${entry_name} 2>/dev/null [[ -n "${reloc_name}${dir_name%/}/${entry_name%/}/.content" ]] && \ mget_http_content ${dir_name%/}/${entry_name} ${reloc_name} >/dev/null 2>&1 ) & let bg_job=1 continue fi $web_client ${host:+"-i${host}"} -f ${dir_name%/}/${entry_name} \ ${reloc_name:+"-odest=${reloc_name%/}"} 2>/dev/null || \ return 1 # output successful - set owner & mode [[ -n $entry_mode ]] && \ $CHMOD $entry_mode ${reloc_name}${dir_name%/}/${entry_name} 2>/dev/null [[ -n $entry_ownr ]] && \ $CHOWN $entry_ownr ${reloc_name}${dir_name%/}/${entry_name} 2>/dev/null # recursion - use some form of iteration later if [[ -n "${reloc_name}${dir_name%/}/${entry_name%/}/.content" ]]; then mget_http_content ${dir_name%/}/${entry_name} ${reloc_name} >/dev/null 2>&1 fi let bg_job=0 wait $! done # wait for any remaining jobs wait fi return 0 }