1#!/bin/ksh -p 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License, Version 1.0 only 7# (the "License"). You may not use this file except in compliance 8# with the License. 9# 10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11# or http://www.opensolaris.org/os/licensing. 12# See the License for the specific language governing permissions 13# and limitations under the License. 14# 15# When distributing Covered Code, include this CDDL HEADER in each 16# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17# If applicable, add the following below this CDDL HEADER, with the 18# fields enclosed by brackets "[]" replaced with your own identifying 19# information: Portions Copyright [yyyy] [name of copyright owner] 20# 21# CDDL HEADER END 22# 23# 24# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27#ident "%Z%%M% %I% %E% SMI" 28 29export PATH=/usr/bin:/usr/sbin:/usr/ccs/bin 30unset ENV TMPDIR 31umask 022 32cwd=$PWD 33 34if [[ -n "$CODEMGR_WS" ]]; then 35 sysroot=$CODEMGR_WS/proto/root_`uname -p` 36elif [[ -n "$ROOT" ]]; then 37 sysroot=$ROOT 38else 39 sysroot=/ 40fi 41 42quote= 43eol='\' 44files= 45 46simchan=com.sun:fm:fmd$$ 47simroot=/tmp/fmd.$$ 48simscript=run 49simpid= 50 51truss_cmd= 52truss_args= 53dump_args= 54inj_args= 55fmd_args= 56 57opt_h=false 58opt_i=false 59opt_s=false 60opt_x=false 61 62function cp_so 63{ 64 nm -ghp $1 2>/dev/null | while read addr type name; do 65 [[ $type != T ]] && continue 66 case $name in 67 _fmd_init) cp $1 $2/usr/lib/fm/fmd/plugins; return ;; 68 fmd_fmri_nvl2str) cp $1 $2/usr/lib/fm/fmd/schemes; return ;; 69 topo_load) cp $1 $2/usr/lib/fm/topo; return ;; 70 esac 71 done 72 die "\nunknown .so type -- $1" 73} 74 75function list_cmds 76{ 77 for cmd in fmadm fmdump fmstat; do 78 echo usr/sbin/$cmd 79 done 80} 81 82function wait_status 83{ 84 if [[ $1 -gt 128 ]]; then 85 sig=$(kill -l $(($1 - 128))) 86 die "fmd terminated from signal $sig (see $simroot)" 87 elif [[ $1 -ne 0 ]]; then 88 die "fmd terminated with status $1 (see $simroot)" 89 fi 90} 91 92function die 93{ 94 echo "fmsim: $*" >& 2 95 [[ -n "$simpid" ]] && exit 1 || exit 2 96} 97 98while [[ $# -gt 0 ]]; do 99 OPTIND=1; while getopts ':d:D:ehio:st:vVx' c; do 100 case "$c" in 101 d) 102 simroot=$OPTARG 103 ;; 104 D) 105 truss_cmd=dtrace 106 truss_args="-s $OPTARG -c" 107 quote="'"; eol="" 108 ;; 109 e|v|V) 110 dump_args="$dump_args -$c" 111 ;; 112 h|i|s|x) 113 eval opt_$c'='true 114 ;; 115 o) 116 fmd_args="$fmd_args -o $OPTARG" 117 ;; 118 t) 119 truss_cmd=truss 120 truss_args="$OPTARG" 121 ;; 122 :) 123 die "option requires an argument -- $OPTARG" 124 ;; 125 *) 126 die "illegal option -- $OPTARG" 127 ;; 128 esac 129 done 130 let OPTIND="$OPTIND - 1"; shift $OPTIND 131 132 if [[ $# -gt 0 ]]; then 133 if [[ -d $1 ]]; then 134 files="$files $1/*" 135 else 136 files="$files $1" 137 fi 138 shift 139 fi 140done 141 142for file in $files; do 143 [[ -r $file ]] || die "input file is missing or not readable -- $file" 144done 145 146if $opt_h || [[ -z "$files" && $opt_i = false ]]; then 147 echo "Usage: fmsim [-ehiksvV] [-d dir] [-D a.d] [-o opt=val]" \ 148 "[-t args] [file ...]" 149 150 echo "\t-D start fmd(1M) using dtrace(1M) and specified D script" 151 echo "\t-e display error log content instead of fault log content" 152 echo "\t-h display usage information for fmsim and exit" 153 echo "\t-i set interactive mode: do not stop after sending events" 154 echo "\t-o set fmd(1M) option to specified value during simulation" 155 echo "\t-s set up simulation world but do not actually run simulation" 156 echo "\t-t start fmd(1M) using truss(1) and specified arguments" 157 echo "\t-v set verbose mode: display additional event detail" 158 echo "\t-V set very verbose mode: display complete event contents" 159 echo "\t-x delete simulation world if simulation is successful" 160 161 exit 0 162fi 163 164echo "fmsim: creating simulation world $simroot ... \c" 165[[ -d $simroot ]] || mkdir -p $simroot || exit 1 166cd $simroot || exit 1 167echo "done." 168 169echo "fmsim: populating /var ... \c" 170mkdir -p -m 0755 var/fm/fmd 171mkdir -p -m 0700 var/fm/fmd/ckpt 172mkdir -p -m 0700 var/fm/fmd/rsrc 173echo "done." 174 175echo "fmsim: populating /usr/lib/fm from $sysroot ... \c" 176(cd $sysroot && find usr/lib/fm -depth -print | cpio -pdmu $simroot) 177 178for platdir in $sysroot/usr/platform/*/lib/fm; do 179 [[ -d $platdir ]] && platdir=${platdir#$sysroot} || continue 180 echo "fmsim: populating $platdir from $sysroot ... \c" 181 (cd $sysroot && find ${platdir#/} -depth -print | cpio -pdmu $simroot) 182done 183 184echo "fmsim: populating /usr/lib/locale/$LANG from $sysroot ... \c" 185(cd $sysroot && find usr/lib/locale/$LANG -depth -print | cpio -pdmu $simroot) 186 187echo "fmsim: populating /usr/sbin from $sysroot ... \c" 188(cd $sysroot && list_cmds | cpio -pdmu $simroot) 189 190echo "fmsim: adding customizations:\c" 191cd $cwd || exit $1 192 193for file in $files; do 194 base=$(basename $file) 195 case $base in 196 *.cmd) die "\neversholt command file not yet supported -- $file" ;; 197 fmd.conf) cp $file $simroot/etc/fm/fmd ;; 198 *.conf) cp $file $simroot/usr/lib/fm/fmd/plugins ;; 199 *.dict) cp $file $simroot/usr/lib/fm/dict ;; 200 *.eft) die "\neversholt fault tree file not yet supported -- $file" ;; 201 *.esc) die "\neversholt source file not yet supported -- $file" ;; 202 *.inj) inj_args="$inj_args $file" ;; 203 *.log) inj_args="$inj_args $file" ;; 204 *log) inj_args="$inj_args $file" ;; 205 *.mo) cp $file $simroot/usr/lib/locale/$LANG/LC_MESSAGES ;; 206 *.so) cp_so $file $simroot ;; 207 *.topo) cp $file $simroot/usr/lib/fm/topo ;; 208 *) die "\nunknown file type or suffix -- $file" ;; 209 esac 210 echo " $base\c" 211done 212 213cd $simroot || exit 1 214echo " done." 215 216echo "fmsim: generating script ... \c" 217cat >$simscript <<EOS 218#!/bin/ksh -p 219# 220# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 221# Use is subject to license terms. 222# 223#ident "%Z%%M% %I% %E% SMI" 224 225# 226# fmsim(1M) script generated for $simroot $(date) 227# 228 229export LD_LIBRARY_PATH=$simroot/usr/lib 230export LD_LIBRARY_PATH_64=$simroot/usr/lib/64 231 232exec $truss_cmd $truss_args $quote./usr/lib/fm/fmd/fmd -R $simroot $eol 233 -o fg=true -o rpc.adm.path=$simroot/rpc -o xprt.device=/dev/null $eol 234 -o errchan=$simchan -o clock=simulated $fmd_args$quote 235 236EOS 237 238chmod 0555 $simscript 239echo "done." 240 241if $opt_s; then 242 echo "fmsim: simulation is saved in $simroot" 243 exit 0 244fi 245 246export LD_LIBRARY_PATH=$simroot/usr/lib 247export LD_LIBRARY_PATH_64=$simroot/usr/lib/64 248 249echo "fmsim: simulation $$ running fmd(1M)\c" 250./usr/lib/fm/fmd/fmd -V | cut -d: -f2 251 252./$simscript & 253simpid=$! 254trap '' INT HUP 255cd $cwd 256i=0 257 258while [[ ! -s $simroot/rpc ]]; do 259 [[ $i -ge 30 ]] && kill -9 $simpid >/dev/null 2>&1 260 kill -0 $simpid >/dev/null 2>&1 || break 261 let i="$i + 1" 262 sleep 1 263done 264 265kill -0 $simpid >/dev/null 2>&1 || { 266 wait $simpid 267 wait_status $? 268} 269 270echo "fmsim: rpc adm requests can rendezvous at" $(<$simroot/rpc) 271echo "fmsim: injectors should use channel $simchan" 272echo "fmsim: debuggers should attach to PID $simpid" 273 274for arg in $inj_args; do 275 echo "fmsim: injecting events from $arg ... \c" 276 $simroot/usr/lib/fm/fmd/fminject -q -c $simchan $arg || { 277 echo "fmsim: fminject failed for $arg: aborting simulation" >& 2 278 kill $simpid >/dev/null 2>&1 279 } 280 echo "done." 281done 282 283if [[ $opt_i = false ]]; then 284 echo "fmsim: injecting event to advance to end-of-time ... \c" 285 echo 'endhrtime;' | $simroot/usr/lib/fm/fmd/fminject -q -c $simchan - 286 echo "done." 287fi 288 289wait $simpid 290status=$? 291 292if [[ -f $simroot/var/fm/fmd/errlog ]]; then 293 echo; $simroot/usr/sbin/fmdump -R $simroot $dump_args; echo 294fi 295 296wait_status $status 297$opt_x && rm -rf $simroot 298exit 0 299