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 2005 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 34isa=$(uname -p) 35if [[ $isa = sparc ]]; then 36 isa64=sparcv9 37elif [[ $isa = i386 ]]; then 38 isa64=amd64 39else 40 isa64=unknown 41fi 42 43if [[ -n "$CODEMGR_WS" ]]; then 44 sysroot=$CODEMGR_WS/proto/root_$isa 45elif [[ -n "$ROOT" ]]; then 46 sysroot=$ROOT 47else 48 sysroot=/ 49fi 50 51quote= 52eol='\' 53files= 54 55simchan=com.sun:fm:fmd$$ 56simroot=/tmp/fmd.$$ 57simscript=run 58simpid= 59 60truss_cmd= 61truss_args= 62dump_args= 63inj_args= 64fmd_args= 65 66opt_h=false 67opt_i=false 68opt_s=false 69opt_w=false 70opt_x=false 71 72function cp_so 73{ 74 nm -ghp $1 2>/dev/null | while read addr type name; do 75 [[ $type != T ]] && continue 76 case $name in 77 _fmd_init) cp $1 $2/usr/lib/fm/fmd/plugins; return ;; 78 fmd_fmri_nvl2str) cp $1 $2/usr/lib/fm/fmd/schemes; return ;; 79 topo_load) cp $1 $2/usr/lib/fm/topo; return ;; 80 esac 81 done 82 die "\nunknown .so type -- $1" 83} 84 85function list_cmds 86{ 87 for cmd in fmadm fmdump fmstat; do 88 echo usr/sbin/$cmd 89 done 90} 91 92function wait_status 93{ 94 if [[ $1 -gt 128 ]]; then 95 sig=$(kill -l $(($1 - 128))) 96 die "fmd terminated from signal $sig (see $simroot)" 97 elif [[ $1 -ne 0 ]]; then 98 die "fmd terminated with status $1 (see $simroot)" 99 fi 100} 101 102function wait_prompt 103{ 104 echo "fmsim: [ Press return to $* ] \c" 105 mode=$(stty -g) 106 stty -echo -isig min 1 time 0 107 read s; echo 108 stty $mode 109} 110 111function die 112{ 113 echo "fmsim: $*" >& 2 114 $opt_w && wait_prompt exit 115 [[ -n "$simpid" ]] && exit 1 || exit 2 116} 117 118while [[ $# -gt 0 ]]; do 119 OPTIND=1; while getopts ':d:D:ehio:st:vVwx' c; do 120 case "$c" in 121 d) 122 simroot=$OPTARG 123 ;; 124 D) 125 truss_cmd=dtrace 126 truss_args="-s $OPTARG -c" 127 quote="'"; eol="" 128 ;; 129 e|v|V) 130 dump_args="$dump_args -$c" 131 ;; 132 h|i|s|w|x) 133 eval opt_$c'='true 134 ;; 135 o) 136 fmd_args="$fmd_args -o $OPTARG" 137 ;; 138 t) 139 truss_cmd=truss 140 truss_args="$OPTARG" 141 ;; 142 :) 143 die "option requires an argument -- $OPTARG" 144 ;; 145 *) 146 die "illegal option -- $OPTARG" 147 ;; 148 esac 149 done 150 let OPTIND="$OPTIND - 1"; shift $OPTIND 151 152 if [[ $# -gt 0 ]]; then 153 if [[ -d $1 ]]; then 154 files="$files $1/*" 155 else 156 files="$files $1" 157 fi 158 shift 159 fi 160done 161 162for file in $files; do 163 [[ -r $file ]] || die "input file is missing or not readable -- $file" 164done 165 166if $opt_h || [[ -z "$files" && $opt_i = false ]]; then 167 echo "Usage: fmsim [-ehisvVwx] [-d dir] [-D a.d] [-o opt=val]" \ 168 "[-t args] [file ...]" 169 170 echo "\t-d set the simulation root directory to the given location" 171 echo "\t-D start fmd(1M) using dtrace(1M) and specified D script" 172 echo "\t-e display error log content instead of fault log content" 173 echo "\t-h display usage information for fmsim and exit" 174 echo "\t-i set interactive mode: do not stop after sending events" 175 echo "\t-o set fmd(1M) option to specified value during simulation" 176 echo "\t-s set up simulation world but do not actually run simulation" 177 echo "\t-t start fmd(1M) using truss(1) and specified arguments" 178 echo "\t-v set verbose mode: display additional event detail" 179 echo "\t-V set very verbose mode: display complete event contents" 180 echo "\t-w wait for a keypress after simulation completes" 181 echo "\t-x delete simulation world if simulation is successful" 182 183 exit 0 184fi 185 186echo "fmsim: creating simulation world $simroot ... \c" 187[[ -d $simroot ]] || mkdir -p $simroot || exit 1 188cd $simroot || exit 1 189echo "done." 190 191echo "fmsim: populating /var ... \c" 192mkdir -p -m 0755 var/fm/fmd 193mkdir -p -m 0700 var/fm/fmd/ckpt 194mkdir -p -m 0700 var/fm/fmd/rsrc 195mkdir -p -m 0700 var/fm/fmd/xprt 196echo "done." 197 198echo "fmsim: populating /usr/lib/fm from $sysroot ... \c" 199(cd $sysroot && find usr/lib/fm -depth -print | cpio -pdmu $simroot) 200 201for platdir in $sysroot/usr/platform/*/lib/fm; do 202 [[ -d $platdir ]] && platdir=${platdir#$sysroot} || continue 203 echo "fmsim: populating $platdir from $sysroot ... \c" 204 (cd $sysroot && find ${platdir#/} -depth -print | cpio -pdmu $simroot) 205done 206 207echo "fmsim: populating /usr/lib/locale/$LANG from $sysroot ... \c" 208(cd $sysroot && find usr/lib/locale/$LANG -depth -print | cpio -pdmu $simroot) 209 210echo "fmsim: populating /usr/sbin from $sysroot ... \c" 211(cd $sysroot && list_cmds | cpio -pdmu $simroot) 212 213echo "fmsim: adding customizations:\c" 214cd $cwd || exit $1 215 216for file in $files; do 217 base=$(basename $file) 218 case $base in 219 *.cmd) die "\neversholt command file not yet supported -- $file" ;; 220 fmd.conf) cp $file $simroot/etc/fm/fmd ;; 221 *.conf) cp $file $simroot/usr/lib/fm/fmd/plugins ;; 222 *.dict) cp $file $simroot/usr/lib/fm/dict ;; 223 *.eft) die "\neversholt fault tree file not yet supported -- $file" ;; 224 *.esc) die "\neversholt source file not yet supported -- $file" ;; 225 *.inj) inj_args="$inj_args $file" ;; 226 *.log) inj_args="$inj_args $file" ;; 227 *log) inj_args="$inj_args $file" ;; 228 *.mo) cp $file $simroot/usr/lib/locale/$LANG/LC_MESSAGES ;; 229 *.so) cp_so $file $simroot ;; 230 *.topo) cp $file $simroot/usr/lib/fm/topo ;; 231 *) die "\nunknown file type or suffix -- $file" ;; 232 esac 233 echo " $base\c" 234done 235 236cd $simroot || exit 1 237echo " done." 238 239echo "fmsim: generating script ... \c" 240cat >$simscript <<EOS 241#!/bin/ksh -p 242# 243# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 244# Use is subject to license terms. 245# 246#ident "%Z%%M% %I% %E% SMI" 247 248# 249# fmsim(1M) script generated for $simroot $(date) 250# 251 252export LD_LIBRARY_PATH=$simroot/usr/lib:$simroot/usr/lib/fm 253export LD_LIBRARY_PATH_64=$simroot/usr/lib/64:$simroot/usr/lib/fm/$isa64 254 255export _THREAD_ERROR_DETECTION=2 256 257exec $truss_cmd $truss_args $quote./usr/lib/fm/fmd/fmd -R $simroot $eol 258 -o fg=true -o clock=simulated $eol 259 -o rpc.adm.prog=0 -o rpc.adm.path=$simroot/rpc $eol 260 -o sysevent-transport:device=/dev/null $eol 261 -o sysevent-transport:channel=$simchan $fmd_args$quote 262 263EOS 264 265chmod 0555 $simscript 266echo "done." 267 268if $opt_s; then 269 echo "fmsim: simulation is saved in $simroot" 270 exit 0 271fi 272 273export LD_LIBRARY_PATH=$simroot/usr/lib:$simroot/usr/lib/fm 274export LD_LIBRARY_PATH_64=$simroot/usr/lib/64:$simroot/usr/lib/fm/$isa64 275 276echo "fmsim: simulation $$ running fmd(1M)\c" 277./usr/lib/fm/fmd/fmd -V | cut -d: -f2 278 279./$simscript & 280simpid=$! 281trap '' INT HUP 282cd $cwd 283i=0 284 285while [[ ! -s $simroot/rpc ]]; do 286 [[ $i -ge 30 ]] && kill -9 $simpid >/dev/null 2>&1 287 kill -0 $simpid >/dev/null 2>&1 || break 288 let i="$i + 1" 289 sleep 1 290done 291 292kill -0 $simpid >/dev/null 2>&1 || { 293 wait $simpid 294 wait_status $? 295} 296 297echo "fmsim: rpc adm requests can rendezvous at" $(<$simroot/rpc) 298echo "fmsim: injectors should use channel $simchan" 299echo "fmsim: debuggers should attach to PID $simpid" 300 301for arg in $inj_args; do 302 echo "fmsim: injecting events from $arg ... \c" 303 $simroot/usr/lib/fm/fmd/fminject -q -c $simchan $arg || { 304 echo "fmsim: fminject failed for $arg: aborting simulation" >& 2 305 kill $simpid >/dev/null 2>&1 306 } 307 echo "done." 308done 309 310if [[ $opt_i = false ]]; then 311 echo "fmsim: injecting event to advance to end-of-time ... \c" 312 echo 'endhrtime;' | $simroot/usr/lib/fm/fmd/fminject -q -c $simchan - 313 echo "done." 314fi 315 316wait $simpid 317status=$? 318 319if [[ -f $simroot/var/fm/fmd/errlog ]]; then 320 echo; $simroot/usr/sbin/fmdump -R $simroot $dump_args; echo 321fi 322 323wait_status $status 324$opt_w && wait_prompt exit 325$opt_x && rm -rf $simroot 326 327exit 0 328