| Gilles Peskine | d1b5f6f | 2020-04-23 17:33:36 +0200 | [diff] [blame] | 1 | ## Common shell functions used by demo scripts programs/*/*.sh. | 
|  | 2 |  | 
|  | 3 | ## How to write a demo script | 
|  | 4 | ## ========================== | 
|  | 5 | ## | 
|  | 6 | ## Include this file near the top of each demo script: | 
|  | 7 | ##   . "${0%/*}/../demo_common.sh" | 
|  | 8 | ## | 
| Gilles Peskine | b2bcdc1 | 2020-04-23 18:50:37 +0200 | [diff] [blame] | 9 | ## Start with a "msg" call that explains the purpose of the script. | 
|  | 10 | ## Then call the "depends_on" function to ensure that all config | 
|  | 11 | ## dependencies are met. | 
|  | 12 | ## | 
| Gilles Peskine | d1b5f6f | 2020-04-23 17:33:36 +0200 | [diff] [blame] | 13 | ## As the last thing in the script, call the cleanup function. | 
|  | 14 | ## | 
|  | 15 | ## You can use the functions and variables described below. | 
|  | 16 |  | 
|  | 17 | set -e -u | 
|  | 18 |  | 
|  | 19 | ## $root_dir is the root directory of the Mbed TLS source tree. | 
|  | 20 | root_dir="${0%/*}" | 
| Gilles Peskine | 911081e | 2020-04-26 22:31:35 +0200 | [diff] [blame] | 21 | # Find a nice path to the root directory, avoiding unnecessary "../". | 
|  | 22 | # The code supports demo scripts nested up to 4 levels deep. | 
|  | 23 | # The code works no matter where the demo script is relative to the current | 
|  | 24 | # directory, even if it is called with a relative path. | 
| Gilles Peskine | d1b5f6f | 2020-04-23 17:33:36 +0200 | [diff] [blame] | 25 | n=4 # limit the search depth | 
|  | 26 | while ! [ -d "$root_dir/programs" ] || ! [ -d "$root_dir/library" ]; do | 
|  | 27 | if [ $n -eq 0 ]; then | 
|  | 28 | echo >&2 "This doesn't seem to be an Mbed TLS source tree." | 
|  | 29 | exit 125 | 
|  | 30 | fi | 
|  | 31 | n=$((n - 1)) | 
|  | 32 | case $root_dir in | 
|  | 33 | .) root_dir="..";; | 
|  | 34 | ..|?*/..) root_dir="$root_dir/..";; | 
|  | 35 | ?*/*) root_dir="${root_dir%/*}";; | 
|  | 36 | /*) root_dir="/";; | 
|  | 37 | *) root_dir=".";; | 
|  | 38 | esac | 
|  | 39 | done | 
|  | 40 |  | 
|  | 41 | ## $programs_dir is the directory containing the sample programs. | 
| Gilles Peskine | 911081e | 2020-04-26 22:31:35 +0200 | [diff] [blame] | 42 | # Assume an in-tree build. | 
| Gilles Peskine | d1b5f6f | 2020-04-23 17:33:36 +0200 | [diff] [blame] | 43 | programs_dir="$root_dir/programs" | 
|  | 44 |  | 
|  | 45 | ## msg LINE... | 
|  | 46 | ## msg <TEXT_ORIGIN | 
|  | 47 | ## Display an informational message. | 
|  | 48 | msg () { | 
|  | 49 | if [ $# -eq 0 ]; then | 
|  | 50 | sed 's/^/# /' | 
|  | 51 | else | 
|  | 52 | for x in "$@"; do | 
|  | 53 | echo "# $x" | 
|  | 54 | done | 
|  | 55 | fi | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | ## run "Message" COMMAND ARGUMENT... | 
|  | 59 | ## Display the message, then run COMMAND with the specified arguments. | 
|  | 60 | run () { | 
|  | 61 | echo | 
|  | 62 | echo "# $1" | 
|  | 63 | shift | 
|  | 64 | echo "+ $*" | 
|  | 65 | "$@" | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | ## Like '!', but stop on failure with 'set -e' | 
|  | 69 | not () { | 
|  | 70 | if "$@"; then false; fi | 
|  | 71 | } | 
|  | 72 |  | 
|  | 73 | ## run_bad "Message" COMMAND ARGUMENT... | 
|  | 74 | ## Like run, but the command is expected to fail. | 
|  | 75 | run_bad () { | 
|  | 76 | echo | 
|  | 77 | echo "$1 This must fail." | 
|  | 78 | shift | 
|  | 79 | echo "+ ! $*" | 
|  | 80 | not "$@" | 
|  | 81 | } | 
|  | 82 |  | 
| Gilles Peskine | 958be36 | 2020-04-23 17:50:26 +0200 | [diff] [blame] | 83 | ## config_has SYMBOL... | 
|  | 84 | ## Succeeds if the library configuration has all SYMBOLs set. | 
|  | 85 | config_has () { | 
|  | 86 | for x in "$@"; do | 
|  | 87 | "$programs_dir/test/query_compile_time_config" "$x" | 
|  | 88 | done | 
|  | 89 | } | 
|  | 90 |  | 
| Gilles Peskine | b2bcdc1 | 2020-04-23 18:50:37 +0200 | [diff] [blame] | 91 | ## depends_on SYMBOL... | 
|  | 92 | ## Exit if the library configuration does not have all SYMBOLs set. | 
|  | 93 | depends_on () { | 
| Gilles Peskine | fc09d27 | 2020-04-26 22:29:57 +0200 | [diff] [blame] | 94 | m= | 
|  | 95 | for x in "$@"; do | 
|  | 96 | if ! config_has "$x"; then | 
|  | 97 | m="$m $x" | 
|  | 98 | fi | 
|  | 99 | done | 
|  | 100 | if [ -n "$m" ]; then | 
| Gilles Peskine | b2bcdc1 | 2020-04-23 18:50:37 +0200 | [diff] [blame] | 101 | cat >&2 <<EOF | 
| Gilles Peskine | fc09d27 | 2020-04-26 22:29:57 +0200 | [diff] [blame] | 102 | $0: this demo requires the following | 
|  | 103 | configuration options to be enabled at compile time: | 
|  | 104 | $m | 
| Gilles Peskine | b2bcdc1 | 2020-04-23 18:50:37 +0200 | [diff] [blame] | 105 | EOF | 
|  | 106 | # Exit with a success status so that this counts as a pass for run_demos.py. | 
|  | 107 | exit | 
|  | 108 | fi | 
|  | 109 | } | 
|  | 110 |  | 
| Gilles Peskine | d1b5f6f | 2020-04-23 17:33:36 +0200 | [diff] [blame] | 111 | ## Add the names of files to clean up to this whitespace-separated variable. | 
|  | 112 | ## The file names must not contain whitespace characters. | 
|  | 113 | files_to_clean= | 
|  | 114 |  | 
| Gilles Peskine | c142620 | 2020-04-26 22:29:12 +0200 | [diff] [blame] | 115 | ## Call this function at the end of each script. | 
|  | 116 | ## It is called automatically if the script is killed by a signal. | 
|  | 117 | cleanup () { | 
|  | 118 | rm -f -- $files_to_clean | 
|  | 119 | } | 
|  | 120 |  | 
| Gilles Peskine | d1b5f6f | 2020-04-23 17:33:36 +0200 | [diff] [blame] | 121 |  | 
|  | 122 |  | 
|  | 123 | ################################################################ | 
|  | 124 | ## End of the public interfaces. Code beyond this point is not | 
|  | 125 | ## meant to be called directly from a demo script. | 
|  | 126 |  | 
| Gilles Peskine | d1b5f6f | 2020-04-23 17:33:36 +0200 | [diff] [blame] | 127 | trap 'cleanup; trap - HUP; kill -HUP $$' HUP | 
|  | 128 | trap 'cleanup; trap - INT; kill -INT $$' INT | 
|  | 129 | trap 'cleanup; trap - TERM; kill -TERM $$' TERM | 
| Gilles Peskine | 958be36 | 2020-04-23 17:50:26 +0200 | [diff] [blame] | 130 |  | 
|  | 131 | if config_has MBEDTLS_ENTROPY_NV_SEED; then | 
|  | 132 | # Create a seedfile that's sufficiently long in all library configurations. | 
|  | 133 | # This is necessary for programs that use randomness. | 
|  | 134 | # Assume that the name of the seedfile is the default name. | 
|  | 135 | files_to_clean="$files_to_clean seedfile" | 
|  | 136 | dd if=/dev/urandom of=seedfile ibs=64 obs=64 count=1 | 
|  | 137 | fi |