diff --git a/run_tmux b/run_tmux index fa53a4d..549196f 100755 --- a/run_tmux +++ b/run_tmux @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash PATH=$PATH:simulator/_bin/linux_release usage() { @@ -13,19 +13,56 @@ Usage: $0 {start|stop|restart|kill|attach|status} attach - Attach to cray simulator session status - List running cray simulator and consoles +Advanced Usage: + + $0 cos_install - Automated COS installation (Do only once) + $0 cos_boot - Automated COS boot (Do only after installation) + $0 cos_shell - Automated log on to COS interactive shell (Do only after boot) + $0 cos_boot_shell - Automated COS boot and log on to interactive shell + +Advanced CLI Usage: + $0 cos_exec - Execute a COS binary (do only after interactive shell logon) + $0 cos_gen_disk - Create a COS extender disk with specified binary + $0 cos_run_disk - Same as above and execute it (do only after interactive shell logon) + EOF } -# Quick tmux help +# Quick help help() { cat << EOF -Run "tmux_run" or "tmux_run attach" to attach to simulator session. -Or use 'tmux attach' or 'tmux attach-session -t cray' -Use keys 'Ctrl b <0 to ...>' to move to specific windows -Use keys 'Ctrl b n' to move to next window -Use keys 'Ctrl b p' to move to previous window -Use keys "Ctrl b d" to detach from simulator session. +Quick Start + +Run "tmux_run attach" to attach to simulator session. +Use keys "Ctrl b w" then "↑/↓ & ↵" to select console. +Use keys "Ctrl b d" to detach and return to shell. +Run "tmux_run stop" to stop simulator session. + +Quick Help + +Attach to Console: + + 1. "tmux_run attach" + 2. "tmux_run" & 5 ↵ + 3. "tmux attach-session -t cray" + 4. "tmux attach" + +Console Navigation: + + 1. "Ctrl b w" & "↑/↓ & ↵" - visual navigation + 2. "Ctrl b <0 to ...>" - to specific console + 3. "Ctrl b n" - next console + 4. "Ctrl b p" - previous console + +Detach from Console: + + 1. "Ctrl b d" - detach from console + +Stop Simulator: + + 1. "tmux_run stop" + 2. "tmux_run" & 1 ↵ EOF } @@ -33,13 +70,19 @@ EOF # Status messages msg() { case "$1" in - "not_up") echo "No cray simulator session is running." ;; - "running") echo "A cray simulator session is already running." ;; - "started") echo "Started!" ;; - "stopped") echo "Stopped!" ;; - "killed") echo "Killed!" ;; - "restarting") echo "Restarting!" ;; - "unknown") echo "Unknown choice: Exiting.";; + "not_up") echo "No cray simulator session is running." ;; + "running") echo "A cray simulator session is already running." ;; + "started") echo "Started!" ;; + "stopped") echo "Stopped!" ;; + "killed") echo "Killed!" ;; + "restarting") echo "Restarting!" ;; + "sent") printf "+" ;; + "matched") printf "=" ;; + "no_match") printf "~" ;; + "timeout") echo "Timed out!" ;; + "no_match_timeout") echo "Query not matched or timed out!" ;; + "no_file") echo "File not found!" ;; + "unknown") echo "Unknown choice: Exiting.";; esac } @@ -53,10 +96,11 @@ start_cray() { if cray_is_up; then msg "running"; else mkdir -p dump disk tape tmux new-session -d -s cray - # Simplify the hooks, they could be error prone - tmux set-hook -t cray -g session-created 'run-shell "tmux list-sessions -F '#{session_name}' | grep '^cray_' | sort | while read -r session; do tmux move-window -s $session:0 -t cray:; done; tmux move-window -s cray:$(tmux list-windows -t cray | grep -n 'cray_sim' | cut -d: -f1) -t cray:0"' - tmux set-hook -t cray -g window-linked 'run-shell "tmux list-windows -t cray -F \"#{window_index}\" | awk '\''$1 != \"0\" {print \"tmux rename-window -t \" $1 \" console_\" NR-1}'\'' | bash"' - tmux send-keys -t cray 'cray_sim cos_117_tmux.cfg' C-m + tmux set -t cray -g status off + tmux set-window-option -t cray -g pane-border-status off + tmux set-hook -t cray -g session-created 'run-shell "./run_tmux merge"' + tmux set-hook -t cray -g window-linked 'run-shell "./run_tmux rename"' + tmux send-keys -t cray 'cray_sim cos_117_tmux.cfg' Enter msg "started" help fi @@ -66,8 +110,8 @@ start_cray() { stop_cray() { if cray_is_up; then tmux select-window -t cray:0 - tmux send-keys -t cray:0 'exit' C-m - tmux send-keys -t cray:0 'exit' C-m + tmux send-keys -t cray:0 'exit' Enter + tmux send-keys -t cray:0 'exit' Enter msg "stopped" else msg "not_up"; fi } @@ -107,19 +151,282 @@ status_cray() { else msg "not_up"; fi } +# Merge all sessions to cray by moving windows. Used as hook. +merge_sessions() { + if cray_is_up; then + tmux list-sessions -F '#{session_name}' | grep '^cray_' | sort | while read -r session; do tmux move-window -s $session:0 -t cray:; done; tmux move-window -s cray:$(tmux list-windows -t cray | grep -n 'cray_sim' | cut -d: -f1) -t cray:0 + else msg "not_up"; fi +} + +# Rename windows to console_(1-n) sequentially. used as hook. +rename_console() { + if cray_is_up; then + for i in $(seq 1 $(tmux display-message -t cray -p '#{session_windows}')); do tmux rename-window -t cray:$i console_$i; done + else msg "not_up"; fi +} + + +# Experimental Automation Section: + +# Send keys or commands to console. +# Usage: send_keys "" +send_keys() { + local window_number=$1 + local command=$2 + + if cray_is_up; then + tmux select-window -t cray:$window_number + tmux send-keys -t cray:$window_number "$command" Enter + msg "sent" + else + msg "not_up" + return 1 + fi +} + +# Check console to see if a string is present. +# Usage check_console "" +check_console() { + local window_number=$1 + local search_string=$2 + + if cray_is_up; then + if tmux capture-pane -t cray:$window_number.0 -pS - | grep -q "xyzzy"; then + echo " " + echo "Automation Stopped!" + exit 1 + elif tmux capture-pane -t cray:$window_number.0 -pS - | grep -q "$search_string"; then + msg "matched" + return 0 + else + msg "no_match" + return 1 + fi + else + msg "not_up" + return 2 + fi +} + + + +# Check console to see if a string is present repeatedly. +# Usage: poll_check_console "" optional: +poll_check_console() { + local window_number=$1 + local search_string=$2 + local interval=${3:-3} + local timeout=${4:-none} + local start_time + local current_time + + if [[ "$timeout" != "none" ]]; then + start_time=$(date +%s) + fi + + while true; do + if check_console "$window_number" "$search_string"; then + msg "matched" + return 0 + fi + + if [[ "$timeout" != "none" ]]; then + current_time=$(date +%s) + if (( current_time - start_time >= timeout )); then + msg "timeout" + return 1 + fi + fi + + sleep "$interval" + done +} + +# Check console for a string repeatedly and send a command if found. +# Usage: poll_check_send "" "" optional: +poll_check_send() { + local window_number=$1 + local search_string=$2 + local command=$3 + local delay=${4:-0} + local target_window_number=${5:-$window_number} + local interval=${6:-3} + local timeout=${7:-none} + + if poll_check_console "$window_number" "$search_string" "$interval" "$timeout"; then + if [[ "$delay" -gt 0 ]]; then + sleep "$delay" + fi + send_keys "$target_window_number" "$command" + else + msg "no_match_timeout" + return 1 + fi +} + +# Automation + +# Create a COS disk with specified file included +create_disk() { + if cray_is_up; then + echo "*** Generating a COS disk with file included ***" + if [ -z "$1" ]; then msg "no_file"; usage; exit 1; fi + local fullpath=$1 + if [ ! -f "$fullpath" ]; then msg "no_file"; usage; exit 1; fi + cp $fullpath /tmp/ + local filename=$(basename "$fullpath") + local cos_filename=$(echo "${filename^^}" | tr -d '_' | sed 's/\.[^.]*$//') + cd target/cos_117 + ./build_exp_disk_swd $fullpath + cd ../.. + echo "File available as \"$cos_filename\"" + echo "*** COS disk generation with file inclusion complete! ***" + else msg "not_up"; fi +} + +# Install COS_117 +cos_install() { + if cray_is_up; then + echo "*** Performing an automated COS 117 install ***" + poll_check_send 1 "AUTODMP" "START COS_117 INSTALL" 5 + poll_check_send 1 "START COMPLETE" "STATION" 2 + sleep 1 + poll_check_send 4 "CRAY STATION" "LOGON" 2 + poll_check_send 4 "COS 1.17" "STMSG" 3 + poll_check_send 4 "TO CONTINUE" "REPLY,0,GO" 1 + poll_check_send 4 "I N S T A L L" "REPLY,1,GO" 2 + poll_check_send 4 "END OF DATA" "STMSG,INFO" 2 + poll_check_send 4 "VALIDATED SUCCESSFULLY" "+" 2 + poll_check_send 4 "STARTUP COMPLETE" "" 3 + echo " " + echo "*** Automated COS 117 install complete! ***" + else msg "not_up"; fi +} + +# Boot COS_117 +cos_deadstart() { + if cray_is_up; then + echo "*** Performing an automated COS 117 boot ***" + poll_check_send 1 "AUTODMP" "START COS_117 DEADSTART" 5 + poll_check_send 1 "START COMPLETE" "STATION" 2 + sleep 1 + poll_check_send 4 "CRAY STATION" "LOGON" 2 + poll_check_send 4 "COS 1.17" "STMSG" 3 + poll_check_send 4 "TO CONTINUE" "REPLY,0,GO" 2 + poll_check_send 4 "TO PROCEED" "REPLY,9,CONTINUE" 3 + poll_check_send 4 "END OF DATA" "STMSG,INFO" 3 + poll_check_send 4 "VALIDATED SUCCESSFULLY" "+" 2 + poll_check_send 4 "STARTUP COMPLETE" "" 3 + echo " " + echo "*** Automated COS 117 boot complete! ***" + else msg "not_up"; fi +} + +# Logon to interactive COS Shell +cos_interactive() { + if cray_is_up; then + echo "*** Performing an automated logon to interactive COS shell ***" + poll_check_send 4 "STARTUP COMPLETE" "CLASS,ALL,ON" 2 + poll_check_send 4 "CLASS" "LIMIT,5" 2 + poll_check_send 4 "LIMIT" "IAIOP LOG" 3 1 + poll_check_send 1 "LOGGED ON" "" 2 4 + poll_check_send 4 "LOGON" "IACON" 3 + poll_check_send 4 ">" "/LOGON" 12 + poll_check_send 4 "ASSEMBLY DATE" "ACCOUNT,AC=CRAY." 3 + poll_check_send 4 "ACCOUNT" "" 3 + echo " " + echo "*** Automated logon to interactive COS shell complete! ***" + else msg "not_up"; fi +} + +# Boot and logon to COS interactive shell +cos_ds_ia() { + if cray_is_up; then + echo "*** Performing an automated boot and logon to interactive COS shell ***" + cos_deadstart + cos_interactive + echo "*** Automated boot and logon to interactive COS shell complete! ***" + else msg "not_up"; fi +} + +# Fetch and execute a file on COS +cos_exec() { + if cray_is_up; then + echo "*** Performing an automated fetch and execution in interactive COS shell ***" + if [ -z "$1" ]; then msg "no_file"; usage; exit 1; fi + local COS_BINARY=$1 + poll_check_send 4 "!" "DISPOSE,DN=$COS_BINARY,MF=AP." 2 + poll_check_send 4 "DISPOSE" "FETCH,DN=$COS_BINARY,MF=AP,AC=ST,TEXT=BIN/$COS_BINARY." 5 + poll_check_send 4 "DATASET RECEIVED FROM FRONT END" "$COS_BINARY." 5 + echo " " + echo "*** Starting execution! ***" + else msg "not_up"; fi +} + +# Create a COS disk with specified file included and run +run_disk() { + if cray_is_up; then + echo "*** Automated execution of specified file ***" + if [ -z "$1" ]; then msg "no_file"; usage; exit 1; fi + local fullpath=$1 + if [ ! -f "$fullpath" ]; then msg "no_file"; usage; exit 1; fi + local filename=$(basename "$fullpath") + local COS_FILENAME=$(echo "${filename^^}" | tr -d '_' | sed 's/\.[^.]*$//') + create_disk $fullpath + cos_exec $COS_FILENAME + echo "*** Execution of $COS_FILENAME started! ***" + else msg "not_up"; fi +} + # Show conditional menu show_menu() { if cray_is_up; then cat << EOF -1. Stop -2. Restart -3. Kill -4. Status -5. Attach +*** Main Options *** + +1. Stop - Stop simulator +2. Restart - Restart simulator +3. Kill - Kill simulator +4. Status - Check simulator status +5. Attach - Attach to simulator screen + +*** Automation Options *** + +6. Boot COS & Load Shell - Boot COS and load interactive shell +7. Load Shell - Load COS interactive shell +8. Boot COS - Boot COS +9. Install COS - Install COS (perform only once!) + +Automation Progress Legends: + + + - Command sent + = - Expected keyword matched + ~ - Expected keyword not yet matched + +Console Magic: + + xyzzy - Stop automation + +Type the above in console and wait for detection. + +Notes: + +- Perform Option 9 only once! +- Use Options 8 or 6 after Option 9 and simulator restart. +- Use Option 7 after Option 9 or 8. +- Other Automation options are incompatible with each other. EOF - else echo "1. Start"; fi + else + cat << EOF + +*** Main Option *** + +1. Start + +EOF + fi } # Pick a choice from conditonal menu @@ -134,6 +441,10 @@ pick_choice() { 3) kill_cray ;; 4) status_cray ;; 5) attach_cray ;; + 6) cos_ds_ia ;; + 7) cos_interactive ;; + 8) cos_deadstart ;; + 9) cos_install ;; *) msg "unknown" ;; esac else @@ -146,11 +457,20 @@ pick_choice() { # Main CLI logic case "$1" in - start) if cray_is_up; then msg "running"; else start_cray; fi ;; - stop) if cray_is_up; then stop_cray; else msg "not_up"; fi ;; - restart) if cray_is_up; then restart_cray; else msg "not_up"; fi ;; - kill) if cray_is_up; then kill_cray; else msg "not_up"; fi ;; - status) if cray_is_up; then status_cray; else msg "not_up"; fi ;; - attach) if cray_is_up; then attach_cray; else msg "not_up"; fi ;; - *) usage; if cray_is_up; then msg "running"; else msg "not_up"; fi; pick_choice ;; + start) if cray_is_up; then msg "running"; else start_cray; fi ;; + stop) if cray_is_up; then stop_cray; else msg "not_up"; fi ;; + restart) if cray_is_up; then restart_cray; else msg "not_up"; fi ;; + kill) if cray_is_up; then kill_cray; else msg "not_up"; fi ;; + status) if cray_is_up; then status_cray; else msg "not_up"; fi ;; + attach) if cray_is_up; then attach_cray; else msg "not_up"; fi ;; + merge) if cray_is_up; then merge_sessions; else msg "not_up"; fi ;; + rename) if cray_is_up; then rename_console; else msg "not_up"; fi ;; + cos_install) if cray_is_up; then cos_install; else msg "not_up"; fi ;; + cos_boot) if cray_is_up; then cos_deadstart; else msg "not_up"; fi ;; + cos_shell) if cray_is_up; then cos_interactive; else msg "not_up"; fi ;; + cos_boot_shell) if cray_is_up; then cos_ds_ia; else msg "not_up"; fi ;; + cos_exec) if cray_is_up; then cos_exec $2; else msg "not_up"; fi ;; + cos_gen_disk) if cray_is_up; then create_disk $2; else msg "not_up"; fi ;; + cos_run_disk) if cray_is_up; then run_disk $2; else msg "not_up"; fi ;; + *) usage; if cray_is_up; then msg "running"; else msg "not_up"; fi; pick_choice ;; esac \ No newline at end of file diff --git a/simulator/httpd/server.cpp b/simulator/httpd/server.cpp index 7c82d7f..623c371 100644 --- a/simulator/httpd/server.cpp +++ b/simulator/httpd/server.cpp @@ -42,7 +42,7 @@ void server::setup(const std::string& address, const std::string& port) boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), boost::lexical_cast(port)); if (address != "*") { boost::asio::ip::tcp::resolver resolver(io_service_); - endpoint = *resolver.resolve({ address, port }); + endpoint = *resolver.resolve(address, port).begin(); } acceptor_.open(endpoint.protocol()); acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); diff --git a/simulator/httpd/server.hpp b/simulator/httpd/server.hpp index 592460f..4974827 100644 --- a/simulator/httpd/server.hpp +++ b/simulator/httpd/server.hpp @@ -45,7 +45,7 @@ private: void do_await_stop(); /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; + boost::asio::io_context io_service_; /// The signal_set is used to register for process termination notifications. boost::asio::signal_set signals_; diff --git a/simulator/sim_lib/console.cpp b/simulator/sim_lib/console.cpp index 2cfc858..ae8f34d 100644 --- a/simulator/sim_lib/console.cpp +++ b/simulator/sim_lib/console.cpp @@ -203,7 +203,7 @@ void Console_c::Tick() { } void Console_c::Poll() { - mIoService.reset(); + mIoService.restart(); mIoService.poll(); } @@ -467,7 +467,7 @@ void Console_c::AcceptIfNeeded(bool aSilent) { } } -boost::asio::io_service Console_c::mIoService; +boost::asio::io_context Console_c::mIoService; #if defined(PARTIAL_DEBUG) && defined(_MSC_VER) #pragma optimize ("", on) diff --git a/simulator/sim_lib/console.h b/simulator/sim_lib/console.h index 1f00656..183d640 100644 --- a/simulator/sim_lib/console.h +++ b/simulator/sim_lib/console.h @@ -101,7 +101,7 @@ protected: boost::optional mConsoleCommand; boost::optional mNewTerminalCommand; - static boost::asio::io_service mIoService; + static boost::asio::io_context mIoService; std::shared_ptr mServerSocket; std::shared_ptr mConnectionSocket; boost::array mReceiveBuf; diff --git a/simulator/sim_lib/iop_concentrator.cpp b/simulator/sim_lib/iop_concentrator.cpp index 2663b15..f8ad62d 100644 --- a/simulator/sim_lib/iop_concentrator.cpp +++ b/simulator/sim_lib/iop_concentrator.cpp @@ -78,7 +78,7 @@ void IopConcentrator_c::ProcessReceivedBytes() { size_t i; size_t size = mReceiveBuf.size(); while (size > 0) { - const uint8_t *data = boost::asio::buffer_cast(mReceiveBuf.data()); + const uint8_t *data = static_cast(mReceiveBuf.data().data()); switch (mRcvState) { case State_RcvLcpPduLength: // process 4-byte PDU length value if (size < 4) return; @@ -325,7 +325,7 @@ void IopConcentrator_c::Tick() { } } -boost::asio::io_service IopConcentrator_c::mIoService; +boost::asio::io_context IopConcentrator_c::mIoService; ///////////////////////////////////////////////////////// // IopConcentratorChannel_c diff --git a/simulator/sim_lib/iop_concentrator.h b/simulator/sim_lib/iop_concentrator.h index 52a3dd9..5fd28eb 100644 --- a/simulator/sim_lib/iop_concentrator.h +++ b/simulator/sim_lib/iop_concentrator.h @@ -147,7 +147,7 @@ protected: std::shared_ptr mConnectionSocket; std::vector mFromCrayData; IopConcentratorChannel_c mInputChannel; - static boost::asio::io_service mIoService; + static boost::asio::io_context mIoService; uint8_t mLastRcvdMessageCode; uint8_t mLastXmitMessageCode; std::shared_ptr mListenSocket; diff --git a/target/cos_117/build_exp_disk_swd b/target/cos_117/build_exp_disk_swd new file mode 100755 index 0000000..9ed7b48 --- /dev/null +++ b/target/cos_117/build_exp_disk_swd @@ -0,0 +1,92 @@ +#!/bin/bash +PATH=$PATH:../../simulator/_bin/cygwin_release:../../simulator/_bin/linux_release:../../bin + +usage() { +cat << EOF + +Generate COS disk which includes specified file + +Usage: $0 + +Note: +- File will be included as all caps with no extension + +EOF +} + +# Sanity checks +if [ -z "$1" ]; then usage; exit 1; fi + +fullpath=$1 +filename=$(basename "$fullpath") + +if [ -f "$fullpath" ]; then cp "$fullpath" "/tmp/$filename"; fi +if [ ! -f "/tmp/$filename" ]; then usage; exit 1; fi + +COS_FILENAME=$(echo "${filename^^}" | tr -d '_' | sed 's/\.[^.]*$//') + +mkdir -p _obj + +ds_edit c -aa disk_content/station/jdiaggo_0.txt -aa disk_content/station/jdiaggo_1.txt -o _obj/jdiaggo.job +ds_edit c -aa disk_content/station/jflush.txt -o _obj/jflush.job +ds_edit c -aa disk_content/station/jgencat_0.txt -aa disk_content/station/jgencat_1.txt -o _obj/jgencat.job +ds_edit c -aa disk_content/station/jinstall_0.txt -aa disk_content/station/jinstall_1.txt -aa disk_content/station/jinstall_2.txt -aa disk_content/station/jinstall_3.txt -o _obj/jinstall.job +ds_edit c -aa disk_content/station/jsysdir.txt -o _obj/jsysdir.job +ds_edit c -aa disk_content/station/jtest30.txt -o _obj/jtest30.job +ds_edit c -aa disk_content/station/recall_0.txt -aa disk_content/station/recall_1.txt -o _obj/recall.job + +ds_edit c -a disk_content/bin/audit.bin -o _obj/audit.ds +ds_edit c -a disk_content/bin/dmp10.bin -o _obj/dmp10.ds +ds_edit c -a disk_content/bin/gencat.bin -o _obj/gencat.ds +ds_edit c -a disk_content/bin/jcsdef.bin -o _obj/jcsdef.ds +ds_edit c -a disk_content/bin/loadcat.bin -o _obj/loadcat.ds +ds_edit c -a disk_content/bin/pld10.bin -o _obj/pld10.ds +ds_edit c -a disk_content/bin/prvdef.bin -o _obj/prvdef.ds +ds_edit c -a disk_content/bin/tedi.bin -o _obj/tedi.ds +ds_edit c -a disk_content/bin/acctdef.bin -o _obj/acctdef.ds +ds_edit c -a disk_content/bin/recio.bin -o _obj/recio.ds +ds_edit c -a disk_content/bin/reload.bin -o _obj/reload.ds +cp disk_content/bin/recall.ds _obj/recall.ds + +exp_disk_create \ +-l IOS \ +-fixed 0 diskboot.bin \ +-fixed 1 dmp.bin \ +-d STATION \ +-f IOPKERNEL iop_kern.bin \ +-f COS_117 disk_content/station/cos_117_2_hdr.bin \ +-f COS_117_1 disk_content/station/cos_117_1_hdr.bin \ +-f COS_117_2 disk_content/station/cos_117_2_hdr.bin \ +-f JDIAGGO _obj/jdiaggo.job \ +-f JFLUSH _obj/jflush.job \ +-f JGENCAT _obj/jgencat.job \ +-f JINSTALL _obj/jinstall.job \ +-f JSYSDIR _obj/jsysdir.job \ +-f JTEST30 _obj/jtest30.job \ +-f RECALL _obj/recall.job \ +-f DEADSTART disk_content/station/deadstart.param \ +-f RESTART disk_content/station/restart.param \ +-f INSTALL disk_content/station/install.param \ +-f MINSTALL disk_content/station/install_mini.param \ +-d MARK \ +-f $ACCOUNT disk_content/mark/account.ds \ +-f $BULLETIN disk_content/mark/bulletin.ds \ +-f $VALIDATION disk_content/mark/validation.ds \ +-d BIN \ +-f $ACCTDEF _obj/acctdef.ds \ +-f AUDIT _obj/audit.ds \ +-f DMP10 _obj/dmp10.ds \ +-f GENCAT _obj/gencat.ds \ +-f JCSDEF _obj/jcsdef.ds \ +-f LOADCAT _obj/loadcat.ds \ +-f PLD10 _obj/pld10.ds \ +-f PRVDEF _obj/prvdef.ds \ +-f RECALL _obj/recall.ds \ +-f RECIO _obj/recio.ds \ +-f RELOAD _obj/reload.ds \ +-f TEDI _obj/tedi.ds \ +-f "$COS_FILENAME" "/tmp/$filename" \ +-o ../../exp_disk.img + +rm /tmp/$filename +echo "Generated COS disk with $filename included as $COS_FILENAME"