### Build and Install KornShell 93u+m Source: https://context7.com/ksh93/ksh/llms.txt Clone the repository, optionally customize compile-time features, build, run tests, and install the shell. Supports installation to a staging area using DESTDIR. ```sh # Clone the repository git clone https://github.com/ksh93/ksh cd ksh # Optional: customize compile-time features # edit src/cmd/ksh93/SHOPT.sh # Build (parallel with 4 jobs) bin/package make -j4 # Run regression tests bin/package test # Install to /usr/local bin/package install /usr/local # Or: install to a staging area (for packagers) DESTDIR=/tmp/staging bin/package install /usr/local ``` -------------------------------- ### Get Build Help Source: https://github.com/ksh93/ksh/blob/dev/README.md Run 'bin/package help' to access documentation for the build system. ```shell bin/package help ``` -------------------------------- ### Install Xcode Command Line Tools Source: https://github.com/ksh93/ksh/blob/dev/README.md Install the Xcode Command Line Tools on macOS. ```shell xcode-select --install ``` -------------------------------- ### Use Ksh Without Installation Source: https://github.com/ksh93/ksh/blob/dev/README.md Run ksh, its utilities, and autoloadable functions without installing them. ```shell bin/package use ``` -------------------------------- ### Ksh Option Parsing with optget() Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/builtins.html Example demonstrating the use of optget() for parsing command-line arguments in a ksh built-in. Handles options, their arguments, and errors. ```ksh #include while(1) switch(n=optget(argv,"xf:[file]")) { case 'f': file = opt_info.arg; break; case ':': error(ERROR_exit(0), opt_info.arg); break; case '?': error(ERROR_usage(2), opt_info.arg); UNREACHABLE(); } ``` -------------------------------- ### Here-Document Example in Ksh93 Source: https://context7.com/ksh93/ksh/llms.txt Shows how to use a here-document ('<&p- # close write end wait $! ``` ```sh # Multiple coprocesses: move to named file descriptors sort |& exec 5>&p 6<&p # fd 5 = sort's stdin, fd 6 = sort's stdout ``` ```sh print -u5 "banana" print -u5 "apple" print -u5 "cherry" exec 5>&- # signal EOF to sort ``` ```sh read -u6 line1; echo "$line1" # apple read -u6 line2; echo "$line2" # banana read -u6 line3; echo "$line3" # cherry exec 6<&- ``` ```sh # Ping-pong between two coprocesses function responder { while read -r msg; do print "ACK: $msg" done } responder |& print -p "hello" read -p reply echo "$reply" # ACK: hello ``` -------------------------------- ### Temporary File Setup Source: https://github.com/ksh93/ksh/wiki/update-copyright.sh Creates a temporary file for intermediate data and sets up a trap to ensure the temporary file is removed upon script exit, preventing disk space issues. ```sh tmpfile=${TMPDIR:-/tmp}/update-copyright-years.${$}${RANDOM} trap 'exec rm -f $tmpfile' EXIT ``` -------------------------------- ### Initialize Keytable and KEYBD trap in ksh Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/functions/emacs_keybind.txt Set up an associative array to store key bindings and install a KEYBD trap that evaluates the corresponding binding when a key is pressed. This is the foundation for custom keybinding in ksh. ```ksh typeset -A Keytable trap 'eval "${Keytable[${.sh.edchar}]}"' KEYBD ``` -------------------------------- ### Compiling Ksh Built-in on Linux Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/builtins.html Example command for compiling a C source file for a Ksh built-in on Linux, specifying include paths and generating position-independent code. ```bash cc -fpic -I$PACKAGE_ast/include/ast -c hello.c ``` -------------------------------- ### Ksh93 Printf Command Usage Source: https://context7.com/ksh93/ksh/llms.txt Shows examples of using the 'printf' command for formatted output in ksh93, including string padding and floating-point formatting. ```sh printf "% -10s %5d\n" "item" 42 ``` ```sh printf "%08.2f\n" 3.14159 ``` ```sh printf "%b\n" "line1\nline2" ``` -------------------------------- ### Remote Syslog Audit Records Example Source: https://github.com/ksh93/ksh/blob/dev/src/cmd/ksh93/README-AUDIT.md Example of audit records received and stored by a remote syslog daemon via UDP. ```text 2008-12-29 22:09:12 192,169.0.115 500;1230606552;/dev/pts/2; echo ${.sh.version} 2008-12-29 22:09:14 192.169.0.115 500;1230606554;/dev/pts/2; pwd 2008-12-29 22:09:17 192.169.0.115 500;1230606557;/dev/pts/2; id 2008-12-29 22:09:23 192.169.0.115 500;1230606563;/dev/pts/2; date 2008-12-29 22:09:25 192.169.0.115 500;1230606565;/dev/pts/2; exit ``` -------------------------------- ### Configure Build with Custom Flags Source: https://github.com/ksh93/ksh/blob/dev/README.md Export CCFLAGS and LDFLAGS as environment variables before running 'bin/package' to pass custom compiler and linker flags. This example demonstrates creating a 64-bit binary on Solaris using Studio cc. ```shell export CCFLAGS="-m64 -O" LDFLAGS="-m64" bin/package make ``` -------------------------------- ### Variable Discipline: .unset Example Source: https://context7.com/ksh93/ksh/llms.txt Implements a '.unset' variable discipline to perform actions, like cleanup, when a variable is unset. Useful for resource management. ```sh typeset managed_res="resource" function managed_res.unset { print "Cleaning up managed_res" } unset managed_res ``` -------------------------------- ### Variable Discipline: .get Example Source: https://context7.com/ksh93/ksh/llms.txt Implements a '.get' variable discipline to modify the value of a variable when it is read. Useful for masking sensitive data. ```sh typeset secret_key="mysecretkey" function secret_key.get { .sh.value="[REDACTED]" # never expose the real value } echo "$secret_key" ``` -------------------------------- ### Manage Shell Options with `set -o` Source: https://context7.com/ksh93/ksh/llms.txt Control shell behavior using `set -o` and `set +o`. Examples include strict error handling, globbing, safety features, interactive editing modes, and restoring option states. ```sh # Enable strict error handling (exit on error, unset vars, pipeline failure) set -o errexit # or: set -e set -o nounset # or: set -u set -o pipefail # fail if any pipeline command fails # Glob options set -o globstar # enable **/ recursive globbing set -o noglob # or: set -f — disable globbing entirely set -o markdirs # append / to directories in glob results set -o globex # allow extended patterns from field-splitting (1.1+) # Safety / compat set -o noclobber # prevent > from overwriting existing files set -o posix # enable POSIX-strict mode set -o braceexpand # enable {a,b,c} brace expansion (on by default) # Introspection set -o # list all option names and current states [[ -o pipefail ]] && echo "pipefail is on" # Interactive editor mode set -o emacs # emacs-style line editing set -o vi # vi-style line editing # Restore from saved state old_opts=$(set +o) # capture current option state as reinputtable commands set -e # ... do work ... eval "$old_opts" # restore ``` -------------------------------- ### Build with Alternative Shell and Flags Source: https://github.com/ksh93/ksh/blob/dev/README.md Specify an alternative shell and append compiler/linker flags to the 'bin/package make' command. ```shell bin/package make SHELL=/bin/bash CCFLAGS="-O2 -I/opt/local/include" LDFLAGS="-L/opt/local/lib" ``` -------------------------------- ### Initialize Safe Mode and Path Source: https://github.com/ksh93/ksh/wiki/update-copyright.sh Sets up a safe execution environment by disabling globbing and setting an empty Internal Field Separator. It also prepends a specific directory to the PATH to ensure the use of path-bound built-ins. ```sh set -fCu; IFS='' # safe mode PATH=/opt/ast/bin:$PATH # use path-bound built-ins ``` -------------------------------- ### Extracting substrings from variables Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/faq.html Use the `${varname:offset:len}` syntax to extract a substring of a specified length starting at a given offset. Offsets start at 0, and negative offsets count from the end of the string. ```ksh echo ${varname:offset:len} ``` -------------------------------- ### Direct Mamake Invocation Source: https://github.com/ksh93/ksh/blob/dev/src/cmd/INIT/README-mamake.md To invoke mamake directly, first build the distribution, then enter 'bin/package use' to set up the environment, and finally 'cd' to the object code directory. ```shell bin/package use cd ~ast ``` -------------------------------- ### Variable Discipline: .append Example Source: https://context7.com/ksh93/ksh/llms.txt Implements an '.append' variable discipline to modify strings being appended to a variable, such as adding timestamps. ```sh typeset logbuf="" function logbuf.append { .sh.value+=" [$(date +%T)]" # timestamp each appended string } logbuf+="event1" logbuf+="event2" echo "$logbuf" ``` -------------------------------- ### Self-Reproducing Program in Ksh Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/faq.html A KornShell program that prints its own source code. This example demonstrates string manipulation and here-document usage. ```ksh n=" " q="'" x="cat <<-!" y=! z='n="$n" q="$q" x="$x" y=$y z=$q$z$q$n$x$n$z$n$y' cat <<-! n="$n" q="$q" x="$x" y=$y z=$q$z$q$n$x$n$z$n$y ! ``` -------------------------------- ### Variable Discipline: .set Example Source: https://context7.com/ksh93/ksh/llms.txt Implements a '.set' variable discipline to intercept and log assignments to a variable. Use for auditing or validation on set. ```sh typeset -C logged_var function logged_var.set { print "Setting logged_var to: ${.sh.value}" .sh.value="${.sh.value}" # accept the new value } logged_var="hello" ``` -------------------------------- ### Interactive Menus with `select` in ksh93 Source: https://context7.com/ksh93/ksh/llms.txt Demonstrates the `select` compound command for creating interactive menus. It shows how to define a prompt (PS3), present options, and process user choices using a `case` statement, including handling dynamic menus populated from arrays. ```sh # Simple menu PS3="Choose an option: " select choice in "Start" "Stop" "Restart" "Quit"; do case $choice in Start) echo "Starting service..."; break;; Stop) echo "Stopping service..."; break;; Restart) echo "Restarting service..."; break;; Quit) echo "Bye!"; break;; *) echo "Invalid choice: $REPLY";; esac done # Output: # 1) Start # 2) Stop # 3) Restart # 4) Quit # Choose an option: 1 # Starting service... ``` ```sh # Dynamic menu from array typeset -a servers=("web1.example.com" "web2.example.com" "db.example.com") PS3="Select server to connect: " select srv in "${servers[@]}" "Cancel"; do [[ $srv == "Cancel" ]] && break [[ -n $srv ]] && { ssh "$srv"; break; } echo "Invalid selection" done ``` -------------------------------- ### Accessing Associative Array Subscript Names in Ksh Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/faq.html Use the prefix operator '!' in variable expansions to get the names of subscripts for associative or indexed arrays. ```ksh ${!var[@]} ``` -------------------------------- ### Signal Handling with `trap` in ksh93 Source: https://context7.com/ksh93/ksh/llms.txt Shows how to use the `trap` command to handle signals (like SIGINT, SIGTERM, EXIT, ERR, DEBUG) and shell pseudo-signals. It demonstrates setting custom handlers, cleaning up resources, and the local scope of traps within ksh-style functions. ```sh # Trap SIGINT (Ctrl+C) and SIGTERM trap 'echo "Caught SIGINT, exiting"; exit 130' INT trap 'echo "Caught SIGTERM, cleaning up"; cleanup; exit 143' TERM ``` ```sh # Cleanup on any exit tmpdir=$(mktemp -d) trap 'rm -rf "$tmpdir"; echo "Cleaned up $tmpdir"' EXIT ``` ```sh # Trap ERR: runs when a command exits non-zero (with set -e) set -o errexit trap 'echo "Error on line $LINENO: command exited with $?"' ERR ``` ```sh # DEBUG trap: runs before each simple command (useful for tracing) trap 'echo "About to run: $BASH_COMMAND"' DEBUG # note: uses .sh.command in ksh trap 'print -u2 "DEBUG line $LINENO: ${.sh.command}"' DEBUG ``` ```sh # List all available signals trap -l # ksh 93u+m 1.1+ ``` ```sh # Ignore a signal trap '' PIPE # ignore SIGPIPE (common in pipelines) ``` ```sh # Restore default handling trap - INT # restore default SIGINT (terminate) ``` ```sh # trap in a ksh-style function is local to that function function safe_section { trap 'echo "local exit handler"' EXIT # This EXIT trap only fires when safe_section returns, not when shell exits } ``` -------------------------------- ### Ksh Built-in Command Structure (C) Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/builtins.html Defines a custom built-in command named 'hello'. It checks for the correct number of arguments and prints a greeting. The SHLIB macro is used for version information. ```c #include int b_hello(int argc, char *argv[], void *context) { if(argc != 2) { fprintf(stderr,"Usage: hello arg\n"); return(2); } printf("hello %s\n",argv[1]); return(0); } SHLIB(hello) ``` -------------------------------- ### Ksh Variable Scoping Example Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/faq.html Demonstrates static variable scoping in ksh93. Variables declared within a function are local to that function unless explicitly passed or accessed differently. ```ksh function f1 { print foo=$foo } function f2 { typeset foo=local f1 } foo=global f2 ``` -------------------------------- ### Efficient File Reading with FILESCAN in ksh93 Source: https://context7.com/ksh93/ksh/llms.txt Demonstrates two methods for reading lines from a file. The first uses a standard `while read` loop, while the second leverages ksh93's FILESCAN feature for potentially faster processing. ```sh while read -r line; do process "$line" done < input.txt ``` ```sh while < input.txt; do process "$REPLY" done ``` -------------------------------- ### Portable `print` command Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/faq.html Use `print` instead of `echo` for portable scripts, as `echo` behavior can vary across systems, especially with arguments starting with `-` or containing special characters. ```ksh print "Hello, world!" ``` -------------------------------- ### Shifting Array Elements in Ksh Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/faq.html To shift array elements, use 'typeset -A' with slicing to create a new array excluding the first element. Note that array subscripts start at 0. ```ksh typeset -A name "${name[@]:1}" ``` -------------------------------- ### Get Git Branch and Year Information Source: https://github.com/ksh93/ksh/wiki/update-copyright.sh Retrieves the current git branch name, the current year, and the commit hash of the first commit of the current year. It includes error handling for each step. ```sh git_branch=$(git branch --show-current) && [[ -n $git_branch ]] || error_out "could not get current git branch" current_year=$(date +%Y) && [[ $current_year =~ ^[0-9]{4}$ ]] || error_out "could not get current year" first_commit=$(git log --since="$current_year-01-01 00:00 UTC" --pretty=format:'%H' | tail -n1) && [[ $first_commit =~ ^[0-9a-f]{40}$ || $first_commit == '' ]] || error_out "could not get the first commit of $current_year" current_commit=$(git log -1 --pretty=format:'%H') && [[ $current_commit =~ ^[0-9a-f]{40}$ ]] || error_out "could not get current commit" ``` -------------------------------- ### ksh93 getopts with Long Options Source: https://context7.com/ksh93/ksh/llms.txt Demonstrates using ksh93's extended getopts to handle both short and long options, including options that require arguments. Use this for robust command-line argument parsing. ```sh # ksh93 getopts supports long options via colon-and-bracket notation while getopts ":ve:t:(dry-run)" opt; do case $opt in v) verbose=true;; e) env="$OPTARG";; t) timeout="$OPTARG";; dry-run) dry_run=true;; ':') print -u2 "Option -$OPTARG requires an argument"; usage;; '?') print -u2 "Unknown option: -$OPTARG"; usage;; esac done shift $(( OPTIND - 1 )) target="${1:?$(usage)}" $verbose && print "Verbose mode on" $dry_run && print "Dry run — no changes will be made" print "Deploying $target to $env (timeout: ${timeout}s)" ``` -------------------------------- ### Autoloading Functions in Ksh93 via FPATH Source: https://context7.com/ksh93/ksh/llms.txt Shows how to configure and use function autoloading in ksh93 by setting the FPATH environment variable and declaring functions. ```sh export FPATH="$HOME/.ksh/functions" # Place function file at $HOME/.ksh/functions/myfunc autoload myfunc # or: typeset -fu myfunc myfunc ``` -------------------------------- ### Resource Limits with ulimit Source: https://context7.com/ksh93/ksh/llms.txt Manages resource limits for the shell and its child processes. Use `ulimit -a` to display all current limits. ```sh # Show all current limits ulimit -a # Output (example): # cpu time (seconds) unlimited # file size (512-byte blocks) unlimited ``` -------------------------------- ### Makefile for Ksh Built-in Shared Library Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/builtins.html A sample Makefile for building a shared library for a Ksh built-in using AT&T nmake. It specifies the target, plugin type, and source files. ```makefile :PACKAGE: --shared ast hello plugin=ksh :LIBRARY: hello.c ``` -------------------------------- ### Get ksh Version Information Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/faq.html Access the current version and release string of ksh using the ${.sh.version} parameter or the $KSH_VERSION environment variable. The format includes compile-time features, release version, and release date. ```ksh echo "${.sh.version}" echo "$KSH_VERSION" ``` -------------------------------- ### Enable ksh93 Compile-Time Options Source: https://github.com/ksh93/ksh/blob/dev/src/cmd/ksh93/README-AUDIT.md Modify SHOPT options in SHOPT.sh to enable or disable accounting and auditing features. Use 0 for disable and 1 for enable, except for SHOPT_AUDITFILE. ```sh SHOPT ACCT=1 # accounting SHOPT ACCTFILE=1 # per-user accounting info SHOPT AUDIT=1 # enable auditing per SHOPT_AUDITFILE SHOPT AUDITFILE='"/etc/ksh_audit"' # auditing file ``` -------------------------------- ### Get CGI Variables Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/scripts/cgi-lib.ksh.txt Retrieves all variables from the Cgi associative array, encodes them using cgi_encode, and formats them into a URL-encoded string suitable for use as a query string or POST body. It initializes the encoding table if it hasn't been already. ```ksh function Cgi.get { typeset i val name vname if [[ ! ${_CGI_c[\]} ]] then val='"' _CGI_c["]=%00 _CGI_c[$var]=%22 _CGI_c[\]]=%27 _CGI_c[\\\]]=%5B _CGI_c[[\]]=%5D _CGI_c[\]]=%5C eval $(cgi_C_init) unset -f cgi_C_init fi vname=${.sh.name} # .sh.name contains variable name .sh.value= # .sh.value stores value for i in ${!Cgi.@} do name=${i#$vname.} nameref v=${i} val=$(cgi_encode "$v") .sh.value="${.sh.value}${.sh.value:+\&}${name}=${val}" done } ``` -------------------------------- ### Build Ksh Source: https://github.com/ksh93/ksh/blob/dev/README.md Build ksh using the package make script. Use 'quiet make' to suppress compiler output. ```shell bin/package make ``` -------------------------------- ### File Descriptor Redirection in Ksh93 Source: https://context7.com/ksh93/ksh/llms.txt Demonstrates opening, writing to, and closing file descriptors (e.g., fd 3 for logging) and reading from them. ```sh exec 3> /tmp/logfile print -u3 "log entry" exec 3>&- ``` ```sh exec 4< /etc/hostname read -u4 hostname exec 4<&- ``` -------------------------------- ### Ksh GMT to UTC Conversion Patch (Not Upstreamed) Source: https://github.com/ksh93/ksh/wiki/Patch-Upstream-Report:-OpenSUSE This patch for GMT to UTC conversion in Ksh's printf %T is not entirely correct. The provided example demonstrates incorrect UTC preference for London time. A corrected version is referenced. ```sh $ LANG=C TZ=Europe/London arch/*/bin/ksh -c 'date; printf %T\n now' Tue Jun 30 01:39:09 BST 2020 Tue Jun 30 00:39:09 UTC 2020 ``` -------------------------------- ### View Shtests Manual Source: https://github.com/ksh93/ksh/blob/dev/README.md Read the manual for the 'shtests' command to control ksh regression test runs. ```shell bin/shtests --man ``` -------------------------------- ### Ksh getopt Function Implementation Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/functions/getopt.txt This function parses command-line options based on a provided option string. It handles options with and without arguments, and also processes remaining arguments after options. ```ksh function getopt { typeset c optstring=$1 options= sep= shift while getopts $optstring c do case $c in [:?]) exit 2 ;; *) options="$options$sep-$c" sep=' ' if [[ $optstring == *$c:* ]] then options=" $options $OPTARG" fi #then print -rn -- " -c" "$OPTARG" #else print -rn -- " -c" ;; esac done print -rn -- "$options" if [[ ${@:$OPTIND-1} != -- ]] then print -rn -- " --" fi if [[ -n ${@:$OPTIND} ]] then print -r -- " ${@:$OPTIND}" fi } ``` -------------------------------- ### Parse CGI Request Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/scripts/cgi-lib.ksh.txt Parses incoming CGI request data. For POST requests, it handles both multipart/form-data (using pax to extract files) and standard form data read from stdin. For GET requests, it uses the QUERY_STRING. It also calls cgi_cookie to parse HTTP_COOKIE. ```ksh function cgi_parse { if [[ $REQUEST_METHOD == POST ]] then if [[ $CONTENT_TYPE == multipart/form-data* ]] then _CGI_multipart=${TMPDIR-/tmp}/cgi-form-$ trap 'rm -rf "$_CGI_multipart"' EXIT mkdir $_CGI_multipart unset -f Cgi.set typeset -A Cgi.file typeset i b v pax --nosummary --read --edit ",.*/,," --edit ",^,$_CGI_multipart/," for i in $_CGI_multipart/* do b=${i##*/} if [[ $b == +([a-z]) ]] then v=$(<$i) eval Cgi.$b='$v' else Cgi.file[$b]=$i fi done else Cgi=$(<&0) # Read from stdin fi else Cgi="$QUERY_STRING" fi cgi_cookie "$HTTP_COOKIE" HEADER["Content-type"]="text/html" } ``` -------------------------------- ### Check Compiled ksh93 Version and Options Source: https://github.com/ksh93/ksh/blob/dev/src/cmd/ksh93/README-AUDIT.md Print the shell version string to verify which options have been compiled into the ksh executable. The option string indicates support for auditing, job control, accounting, and multibyte characters. ```sh $ arch/darwin.i386-64/bin/ksh -c 'echo ${.sh.version}' Version AJLM 93u+m/1.1.0-alpha+dev 2022-01-20 $ arch/darwin.i386-64/bin/ksh -c 'echo $KSH_VERSION' Version AJLM 93u+m/1.1.0-alpha+dev 2022-01-20 ``` -------------------------------- ### Job Control in ksh93 Source: https://context7.com/ksh93/ksh/llms.txt Demonstrates ksh93's job control features, including running jobs in the background, listing them, bringing them to the foreground or background, waiting for them, sending signals, and disowning them. It also covers setting the maximum number of concurrent jobs (JOBMAX) and enabling `pipefail` and `notify` options. ```sh # Run a job in the background sleep 60 & job_pid=$! echo "Started sleep, PID=$job_pid" ``` ```sh # List jobs jobs # show all jobs jobs -l # with PIDs jobs -p # PIDs only ``` ```sh # Bring to foreground / send to background fg %1 # bring job 1 to foreground bg %1 # resume stopped job 1 in background fg %sleep # bring job matching 'sleep' to foreground ``` ```sh # Wait for jobs wait # wait for all background jobs wait $job_pid # wait for specific PID wait %1 # wait for job 1 ``` ```sh # Send signals kill %1 # SIGTERM to job 1 kill -9 %1 # SIGKILL to job 1 kill -STOP %1 # pause job 1 ``` ```sh # Disown: remove from job table (process continues after shell exits) long_running_task & disown $! ``` ```sh # Limit concurrent jobs (JOBMAX) JOBMAX=4 # at most 4 concurrent background jobs # Shell will wait when limit is reached before starting more ``` ```sh # pipefail: detect failures in pipelines set -o pipefail false | true echo "exit: $?" # 1 (false's failure propagates) ``` ```sh # notify: get immediate notification when background job changes state set -o notify sleep 5 & # will print notification as soon as it finishes ``` -------------------------------- ### Ksh Storage Management with stak library Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/builtins.html Illustrates a coding convention for managing dynamic storage using the stak library within a ksh built-in. Ensures memory is freed upon function completion or interrupt. ```c _yourfunction_() { char *savebase; int saveoffset; if(saveoffset=staktell()) savebase = stakfreeze(0); ... if(saveoffset) stakset(savebase,saveoffset); else stakseek(0); } ``` -------------------------------- ### Define and Use Namespaces in ksh93 Source: https://context7.com/ksh93/ksh/llms.txt Shows how to define namespaces to create lexical scopes for variables and functions, preventing name conflicts. Includes nested namespaces and demonstrates isolation from global variables. ```ksh # Define a namespace namespace db { typeset host="localhost" typeset -i port=5432 function connect { print "Connecting to ${db.host}:${db.port}" } function query { print "Query on ${db.host}: $1" } } # Access namespace members with qualified names echo "${db.host}" # localhost db.connect # Connecting to localhost:5432 db.query "SELECT 1" # Query on localhost: SELECT 1 # Namespaces can be nested namespace app { namespace config { typeset version="1.0" } function start { print "Starting app v${app.config.version}" } } app.start # Starting app v1.0 # Variables in a namespace are isolated typeset host="external" echo "$host" # external echo "${db.host}" # localhost — namespace var is separate ``` -------------------------------- ### Initialize CGI URL Encoding Table Source: https://github.com/ksh93/ksh/blob/dev/docs/ksh/scripts/cgi-lib.ksh.txt Initializes the _CGI_c associative array with percent-encoded values for characters that need escaping during URL encoding. It excludes specific characters like quotes, backslashes, and brackets. ```ksh function cgi_C_init { integer i for ((i=1; i < 256; i++)) do if (( i!=16#22 && i!=16#27 && i!=16#5C && i!=16#5B && i!=16#5D )) then printf $'_CGI_c[$\'\\x%.2X\']=%%%.2X\n' $i $i fi done print } ```