1#!/bin/bash 2# ash -- "Adventure shell" 3# last edit: 86/04/21 D A Gwyn 4# SCCS ID: @(#)ash.sh 1.4 5 6OPATH=$PATH 7 8ask() 9{ 10 echo -n "$@" '[y/n] ' 11 read ans 12 13 case "$ans" in 14 y*|Y*) 15 return 0 16 ;; 17 *) 18 return 1 19 ;; 20 esac 21} 22 23CAT=${PAGER:-more} 24 25ash_inst() 26{ 27 cat <<- EOF 28 29 Instructions for the Adventure shell 30 31 Welcome to the Adventure shell! In this exploration of the UNIX file 32 system, I will act as your eyes and hands. As you move around, I will 33 describe whatever is visible and will carry out your commands. The 34 general form of a command is 35 Verb Object Extra_stuff. 36 Most commands pay no attention to the "Extra_stuff", and many do not 37 need an "Object". A typical command is 38 get all 39 which picks up all files in the current "room" (directory). You can 40 find out what you are carrying by typing the command 41 inventory 42 The command "help" results in a full description of all commands that I 43 understand. To quit the Adventure shell, type 44 quit 45 46 There are UNIX monsters lurking in the background. These are also 47 known as "commands with arguments". 48 49 Good luck! 50 EOF 51} 52 53ash_help() 54{ 55echo "I understand the following commands (synonyms in parentheses):" 56echo "" 57 58echo "change OBJECT to NEW_NAME changes the name of the object" 59echo "clone OBJECT as NEW_NAME duplicates the object" 60echo "drop OBJECTS leaves the objects in the room" 61echo "enter (go) PASSAGE takes the labeled passage" 62echo "examine OBJECTS describes the objects in detail" 63echo "feed OBJECT to MONSTER stuffs the object into a UNIX monster" 64echo "get (take) OBJECTS picks up the specified objects" 65echo "gripe (bug) report a problem with the Adventure shell" 66echo "help prints this summary" 67echo "inventory (i) tells what you are carrying" 68echo "kill (destroy) OBJECTS destroys the objects" 69echo "look (l) describes the room, including hidden objects" 70echo "open (read) OBJECT shows the contents of an object" 71echo "quit (exit) leaves the Adventure shell" 72echo "resurrect OBJECTS attempts to restore dead objects" 73echo "steal OBJECT from MONSTER obtains the object from a UNIX monster" 74echo "throw OBJECT at daemon feeds the object to the printer daemon" 75echo "up takes the overhead passage" 76echo "wake MONSTER awakens a UNIX monster" 77echo "where (w) tells you where you are" 78echo "xyzzy moves you to your home" 79} 80 81MAINT=chet@ins.cwru.edu 82 83PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:. 84export PATH 85 86trap 'echo Ouch!' 2 3 87#trap '' 18 # disable Berkeley job control 88 89#ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; } 90ash_lk(){ echo " $1 " | fgrep -q " $2 " >/dev/null 2>&1 ; } 91ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; } 92ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; } 93 94# enable history, bang history expansion, and emacs editing 95set -o history 96set -o histexpand 97set -o emacs 98 99cd 100LIM=.limbo # $HOME/$LIM contains "destroyed" objects 101mkdir $LIM || { 102 echo "ash: cannot mkdir $LIM: exiting" 103 exit 1 104} 105KNAP=.knapsack # $HOME/$KNAP contains objects being "carried" 106if [ ! -d $KNAP ] 107then mkdir $KNAP >/dev/null 2>&1 108 if [ $? = 0 ] 109 then echo 'You found a discarded empty knapsack.' 110 else echo 'You have no knapsack to carry things in.' 111 exit 1 112 fi 113else echo 'One moment while I peek in your old knapsack...' 114fi 115 116kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\`` 117 118if ask 'Welcome to the Adventure shell! Do you need instructions?' 119then 120 ash_inst 121 echo -n 'Type a newline to continue: ' 122 read 123fi 124 125wiz=false 126cha=false 127prev=$LIM 128while : 129do room=`pwd` 130 if [ $room != $prev ] 131 then if [ $room = $HOME ] 132 then echo 'You are in your own home.' 133 else echo "You have entered $room." 134 fi 135 exs= 136 obs= 137 hexs= 138 hobs= 139 f=false 140 for i in `ls -a` 141 do case $i in 142 .|..) ;; 143 .*) if [ -f $i ] 144 then hobs="$hobs $i" 145 elif [ -d $i ] 146 then hexs="$hexs $i" 147 else f=true 148 fi 149 ;; 150 *) if [ -f $i ] 151 then obs="$obs $i" 152 elif [ -d $i ] 153 then exs="$exs $i" 154 else f=true 155 fi 156 ;; 157 esac 158 done 159 if [ "$obs" ] 160 then echo 'This room contains:' 161 ash_pr $obs 162 else echo 'The room looks empty.' 163 fi 164 if [ "$exs" ] 165 then echo 'There are exits labeled:' 166 ash_pr $exs 167 echo 'as well as a passage overhead.' 168 else echo 'There is a passage overhead.' 169 fi 170 if sh -c $f 171 then echo 'There are shadowy figures in the corner.' 172 fi 173 prev=$room 174 fi 175 176 read -e -p '-advsh> ' verb obj x # prompt is '-advsh> ' 177 if [ $? != 0 ] 178 then verb=quit # EOF 179 fi 180 181 case $verb in 182 change) if [ "$obj" ] 183 then if ash_lk "$obs $hobs" "$obj" 184 then set -- $x 185 case "$1" in 186 to) if [ "$2" ] 187 then if [ -f $2 ] 188 then echo "You must destroy $2 first." 189 set -- 190 fi 191 if [ "$2" ] 192 then if mv $obj $2 # >&- 2>&- 193 then echo "The $obj shimmers and turns into $2." 194 obs=`ash_rm "$2 $obs" "$obj"` 195 else echo "There is a cloud of smoke but the $obj is unchanged." 196 fi 197 fi 198 else echo 'To what?' 199 fi 200 ;; 201 *) echo "Change $obj to what?" 202 ;; 203 esac 204 else if ash_lk "$kn" "$obj" 205 then echo 'You must drop it first.' 206 else echo "I see no $obj here." 207 fi 208 fi 209 else echo 'Change what?' 210 fi 211 ;; 212 clone) if [ "$obj" ] 213 then if ash_lk "$obs $hobs" "$obj" 214 then if [ ! -r $obj ] 215 then echo "The $obj does not wish to be cloned." 216 else set -- $x 217 case "$1" in 218 as) if [ "$2" ] 219 then if [ -f $2 ] 220 then echo "You must destroy $2 first." 221 else if cp $obj $2 # >&- 2>&- 222 then echo "Poof! When the smoke clears, you see the new $2." 223 obs="$obs $2" 224 else echo 'You hear a dull thud but no clone appears.' 225 fi 226 fi 227 else echo 'As what?' 228 fi 229 ;; 230 *) echo "Clone $obj as what?" 231 ;; 232 esac 233 fi 234 else if ash_lk "$kn" "$obj" 235 then echo 'You must drop it first.' 236 else echo "I see no $obj here." 237 fi 238 fi 239 else echo 'Clone what?' 240 fi 241 ;; 242 drop) if [ "$obj" ] 243 then for it in $obj $x 244 do if ash_lk "$kn" "$it" 245 then if [ -w $it ] 246 then echo "You must destroy $it first." 247 else if mv $HOME/$KNAP/$it $it # >&- 2>&- 248 then echo "$it: dropped." 249 kn=`ash_rm "$kn" "$it"` 250 obs=`echo $it $obs` 251 else echo "The $it is caught in your knapsack." 252 fi 253 fi 254 else echo "You're not carrying the $it!" 255 fi 256 done 257 else echo 'Drop what?' 258 fi 259 ;; 260 enter|go) if [ "$obj" ] 261 then if [ $obj != up ] 262 then if ash_lk "$exs $hexs" "$obj" 263 then if [ -x $obj ] 264 then if cd $obj 265 then echo 'You squeeze through the passage.' 266 else echo "You can't go that direction." 267 fi 268 else echo 'An invisible force blocks your way.' 269 fi 270 else echo 'I see no such passage.' 271 fi 272 else if cd .. 273 then echo 'You struggle upwards.' 274 else echo "You can't reach that high." 275 fi 276 fi 277 else echo 'Which passage?' 278 fi 279 ;; 280 examine) if [ "$obj" ] 281 then if [ $obj = all ] 282 then $obj=`echo $obs $exs` 283 x= 284 fi 285 for it in $obj $x 286 do if ash_lk "$obs $hobs $exs $hexs" "$it" 287 then echo "Upon close inspection of the $it, you see:" 288 ls -ld $it 2>/dev/null 289 if [ $? != 0 ] 290 then echo "-- when you look directly at the $it, it vanishes." 291 fi 292 else if ash_lk "$kn" "$it" 293 then echo 'You must drop it first.' 294 else echo "I see no $it here." 295 fi 296 fi 297 done 298 else echo 'Examine what?' 299 fi 300 ;; 301 feed) if [ "$obj" ] 302 then if ash_lk "$obs $hobs" "$obj" 303 then set -- $x 304 case "$1" in 305 to) if [ "$2" ] 306 then shift 307 if PATH=$OPATH $* <$obj 2>/dev/null 308 then echo "The $1 monster devours your $obj." 309 if rm -f $obj # >&- 2>&- 310 then obs=`ash_rm "$obs" "$obj"` 311 else echo 'But he spits it back up.' 312 fi 313 else echo "The $1 monster holds his nose in disdain." 314 fi 315 else echo 'To what?' 316 fi 317 ;; 318 *) echo "Feed $obj to what?" 319 ;; 320 esac 321 else if ash_lk "$kn" "$obj" 322 then echo 'You must drop it first.' 323 else echo "I see no $obj here." 324 fi 325 fi 326 else echo 'Feed what?' 327 fi 328 ;; 329 get|take) if [ "$obj" ] 330 then if [ $obj = all ] 331 then obj="$obs" 332 x= 333 fi 334 for it in $obj $x 335 do if ash_lk "$obs $hobs" "$it" 336 then if ash_lk "$kn" "$it" 337 then echo 'You already have one.' 338 else if mv $it $HOME/$KNAP/$it # >&- 2>&- 339 then echo "$it: taken." 340 kn="$it $kn" 341 obs=`ash_rm "$obs" "$it"` 342 else echo "The $it is too heavy." 343 fi 344 fi 345 else echo "I see no $it here." 346 fi 347 done 348 else echo 'Get what?' 349 fi 350 ;; 351 gripe|bug) echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.' 352 cat | mail $MAINT -s 'ash bug' 353 echo 'Thank you!' 354 ;; 355 help) ash_help 356 ;; 357 inventory|i) if [ "$kn" ] 358 then echo 'Your knapsack contains:' 359 ash_pr $kn 360 else echo 'You are poverty-stricken.' 361 fi 362 ;; 363 kill|destroy) if [ "$obj" ] 364 then if [ $obj = all ] 365 then x= 366 if ask "Do you really want to attempt to $verb them all?" 367 then obj=`echo $obs` 368 else echo 'Chicken!' 369 obj= 370 fi 371 fi 372 for it in $obj $x 373 do if ash_lk "$obs $hobs" "$it" 374 then if mv $it $HOME/$LIM # <&- >&- 2>&- 375 then if [ $verb = kill ] 376 then echo "The $it cannot defend himself; he dies." 377 else echo "You have destroyed the $it; it vanishes." 378 fi 379 obs=`ash_rm "$obs" "$it"` 380 else if [ $verb = kill ] 381 then echo "Your feeble blows are no match for the $it." 382 else echo "The $it is indestructible." 383 fi 384 fi 385 else if ash_lk "$kn" "$it" 386 then echo "You must drop the $it first." 387 found=false 388 else echo "I see no $it here." 389 fi 390 fi 391 done 392 else echo 'Kill what?' 393 fi 394 ;; 395 look|l) obs=`echo $obs $hobs` 396 hobs= 397 if [ "$obs" ] 398 then echo 'The room contains:' 399 ash_pr $obs 400 else echo 'The room is empty.' 401 fi 402 exs=`echo $exs $hexs` 403 hexs= 404 if [ "$exs" ] 405 then echo 'There are exits plainly labeled:' 406 ash_pr $exs 407 echo 'and a passage directly overhead.' 408 else echo 'The only exit is directly overhead.' 409 fi 410 ;; 411 magic) if [ "$obj" = mode ] 412 then if sh -c $cha 413 then echo 'You had your chance and you blew it.' 414 else if ask 'Are you a wizard?' 415 then echo -n 'Prove it! Say the magic word: ' 416 read obj 417 if [ "$obj" = armadillo ] 418 then echo 'Yes, master!!' 419 wiz=true 420 else echo "Homie says: I don't think so" 421 cha=true 422 fi 423 else echo "I didn't think so." 424 fi 425 fi 426 else echo 'Nice try.' 427 fi 428 ;; 429 open|read) if [ "$obj" ] 430 then if ash_lk "$obs $hobs" "$obj" 431 then if [ -r $obj ] 432 then if [ -s $obj ] 433 then echo "Opening the $obj reveals:" 434 $CAT < $obj 435 if [ $? != 0 ] 436 then echo '-- oops, you lost the contents!' 437 fi 438 else echo "There is nothing inside the $obj." 439 fi 440 else echo "You do not have the proper tools to open the $obj." 441 fi 442 else if ash_lk "$kn" "$obj" 443 then echo 'You must drop it first.' 444 found=false 445 else echo "I see no $obj here." 446 fi 447 fi 448 else echo 'Open what?' 449 fi 450 ;; 451 quit|exit) if ask 'Do you really want to quit now?' 452 then if [ "$kn" ] 453 then echo 'The contents of your knapsack will still be there next time.' 454 fi 455 rm -rf $HOME/$LIM 456 echo 'See you later!' 457 exit 0 458 fi 459 ;; 460 resurrect) if [ "$obj" ] 461 then for it in $obj $x 462 do if ash_lk "$obs $hobs" "$it" 463 then echo "The $it is already alive and well." 464 else if mv $HOME/$LIM/$it $it # <&- >&- 2>&- 465 then echo "The $it staggers to his feet." 466 obs=`echo $it $obs` 467 else echo "There are sparks but no $it appears." 468 fi 469 fi 470 done 471 else echo 'Resurrect what?' 472 fi 473 ;; 474 steal) if [ "$obj" ] 475 then if ash_lk "$obs $hobs" "$obj" 476 then echo 'There is already one here.' 477 else set -- $x 478 case "$1" in 479 from) if [ "$2" ] 480 then shift 481 if PATH=$OPATH $* >$obj 2>/dev/null 482 then echo "The $1 monster drops the $obj." 483 obs=`echo $obj $obs` 484 else echo "The $1 monster runs away as you approach." 485 rm -f $obj # >&- 2>&- 486 fi 487 else echo 'From what?' 488 fi 489 ;; 490 *) echo "Steal $obj from what?" 491 ;; 492 esac 493 fi 494 else echo 'Steal what?' 495 fi 496 ;; 497 throw) if [ "$obj" ] 498 then if ash_lk "$obs $hobs" "$obj" 499 then set -- $x 500 case "$1" in 501 at) case "$2" in 502 daemon) if sh -c "lpr -r $obj" 503 then echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket." 504 obs=`ash_rm "$obs" "$obj"` 505 else echo "The daemon is nowhere to be found." 506 fi 507 ;; 508 *) echo 'At what?' 509 ;; 510 esac 511 ;; 512 *) echo "Throw $obj at what?" 513 ;; 514 esac 515 else if ash_lk "$kn" "$obj" 516 then echo 'It is in your knapsack.' 517 found=false 518 else echo "I see no $obj here." 519 fi 520 fi 521 else echo 'Throw what?' 522 fi 523 ;; 524 u|up) if cd .. 525 then echo 'You pull yourself up a level.' 526 else echo "You can't reach that high." 527 fi 528 ;; 529 wake) if [ "$obj" ] 530 then echo "You awaken the $obj monster:" 531 PATH=$OPATH $obj $x 532 echo 'The monster slithers back into the darkness.' 533 else echo 'Wake what?' 534 fi 535 ;; 536 w|where) echo "You are in $room." 537 ;; 538 xyzzy) if cd 539 then echo 'A strange feeling comes over you.' 540 else echo 'Your spell fizzles out.' 541 fi 542 ;; 543 *) if [ "$verb" ] 544 then if sh -c $wiz 545 then PATH=$OPATH $verb $obj $x 546 else echo "I don't know how to \"$verb\"." 547 echo 'Type "help" for assistance.' 548 fi 549 else echo 'Say something!' 550 fi 551 ;; 552 esac 553done 554