├── tests ├── env2.sh ├── random-seed.txt ├── echo1.sh ├── echo2.sh ├── var0.sh ├── fstab ├── var2.sh ├── catinput.sh ├── echo0.sh ├── env.sh ├── tildaexpansion.sh ├── echo3.sh ├── async.sh ├── echo4.sh ├── special.sh ├── upper0.sh ├── exit.sh ├── for5.sh ├── lower0.sh ├── for2.sh ├── sushell ├── redirection0.sh ├── if5.sh ├── devpts ├── for6.sh ├── pipeline0.sh ├── redir.sh ├── for8.sh ├── functions1.sh ├── perf.text ├── local.sh ├── until.sh ├── 2.1.sh ├── arguments.sh ├── env3.sh ├── if10.sh ├── hostname0.sh ├── if4.sh ├── for7.sh ├── while0.sh ├── lower.sh ├── upper.sh ├── for1.sh ├── if1.sh ├── showsize.sh ├── for4.sh ├── array.sh ├── for3.sh ├── readfile.sh ├── if3.sh ├── alignment.sh ├── functions3.sh ├── reboot ├── functions0.sh ├── redirect.sh ├── dmesg.sh ├── array0.sh ├── 3.1.sh ├── if9.sh ├── 9.9.sh ├── braceexpansion.sh ├── save-rtc.sh ├── split.sh ├── 9.4.sh ├── parameterexpansion.sh ├── sendsigs ├── conditionals.sh ├── redirection.sh ├── 2.2.sh ├── 6.1.sh ├── if6.sh ├── if8.sh ├── replacement.sh ├── banner.sh ├── pipeline.sh ├── halt ├── umountfs ├── devpts.sh ├── for.sh ├── read.sh ├── regex.sh ├── hostname.sh ├── rmnologin.sh ├── single ├── 9.8.sh ├── emptyvar.sh ├── functions2.sh ├── 4.2.sh ├── 9.5.sh ├── 4.3.sh ├── 4.7.sh ├── 7.5.sh ├── umountnfs.sh ├── arithmetic.sh ├── files.cpp ├── 4.6.sh ├── dirname.sh ├── substring.sh ├── if7.sh ├── 9.3.sh ├── while.sh ├── mountall.sh ├── 3.2.sh ├── 6.2.sh ├── 4.5.sh ├── 7.7.sh ├── stringconcat.sh ├── sysfs.sh ├── 7.2.sh ├── variables.sh ├── 3.3.sh ├── 5.1.sh ├── 3.4.sh ├── 9.6.sh ├── checkfs.sh ├── 8.2.sh ├── 8.3.sh ├── read-only-rootfs-hook.sh ├── 9.2.sh ├── case.sh ├── urandom ├── logic.sh ├── default0.sh ├── 8.5.sh ├── 7.3.sh ├── wordexp.cpp ├── 8.4.sh ├── 9.1.sh ├── 7.4.sh ├── 8.1.sh ├── mountnfs.sh ├── var1.sh ├── 7.6.sh ├── 4.4.sh ├── bootmisc.sh ├── 5.3.sh ├── 2.3.sh ├── functions ├── if.sh ├── exec.c ├── 5.2.sh ├── 7.1.sh ├── 9.7.sh ├── case0.sh ├── expansions.sh ├── for0.sh ├── 4.1.sh ├── checkroot.sh ├── if2.sh ├── exec.cpp ├── if0.sh ├── pipe2.c └── populate-volatile.sh ├── perf.sh ├── gperf.sh ├── gprof.sh ├── .gitmodules ├── tsconfig.json ├── LICENSE ├── bash2cpp.sln ├── .github └── workflows │ ├── node.js.yml │ └── codeql-analysis.yml ├── package.json ├── .gitattributes ├── bash2cpp.njsproj ├── .gitignore ├── README.md └── test.py /tests/env2.sh: -------------------------------------------------------------------------------- 1 | value="hello" -------------------------------------------------------------------------------- /tests/random-seed.txt: -------------------------------------------------------------------------------- 1 | 12355 2 | -------------------------------------------------------------------------------- /tests/echo1.sh: -------------------------------------------------------------------------------- 1 | echo '$((42 * 42))' 2 | -------------------------------------------------------------------------------- /tests/echo2.sh: -------------------------------------------------------------------------------- 1 | echo "Testing \"0\"" 2 | -------------------------------------------------------------------------------- /tests/var0.sh: -------------------------------------------------------------------------------- 1 | echo " Today=$(date +%d-%m-%y)" -------------------------------------------------------------------------------- /perf.sh: -------------------------------------------------------------------------------- 1 | perf record -F 10000 -g $1 2 | perf report 3 | -------------------------------------------------------------------------------- /tests/fstab: -------------------------------------------------------------------------------- 1 | LABEL=cloudimg-rootfs / ext4 defaults 0 0 2 | -------------------------------------------------------------------------------- /tests/var2.sh: -------------------------------------------------------------------------------- 1 | EXEC=" 2 | touch \"$1\"; 3 | " 4 | echo $EXEC -------------------------------------------------------------------------------- /tests/catinput.sh: -------------------------------------------------------------------------------- 1 | cat << __EOF__ 2 | my text 3 | __EOF__ 4 | -------------------------------------------------------------------------------- /tests/echo0.sh: -------------------------------------------------------------------------------- 1 | x=3 2 | echo $(( x++ )) 3 | echo $(( x++ )) 4 | -------------------------------------------------------------------------------- /tests/env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source tests/env2.sh 3 | echo $value -------------------------------------------------------------------------------- /tests/tildaexpansion.sh: -------------------------------------------------------------------------------- 1 | a=~/subdir:~/othersubdir/ciao 2 | echo $a -------------------------------------------------------------------------------- /tests/echo3.sh: -------------------------------------------------------------------------------- 1 | PROG=v 2 | val="sinan kaya" 3 | echo "${PROG} "$val": msg" 4 | -------------------------------------------------------------------------------- /tests/async.sh: -------------------------------------------------------------------------------- 1 | echo "hello1" & 2 | echo "hello2" & 3 | echo "hello3" & 4 | wait 5 | -------------------------------------------------------------------------------- /tests/echo4.sh: -------------------------------------------------------------------------------- 1 | val=sinan 2 | echo 'hello$val ? \r\n' 3 | 4 | 5 | echo "hello$val" 6 | -------------------------------------------------------------------------------- /tests/special.sh: -------------------------------------------------------------------------------- 1 | c="s k" 2 | # echo -e "d "$c": a/b c" 3 | printf "n\na\nc\n\n\nd\n" 4 | -------------------------------------------------------------------------------- /tests/upper0.sh: -------------------------------------------------------------------------------- 1 | name='fahmida' 2 | echo $name 3 | echo ${name^} 4 | echo ${name^^} 5 | -------------------------------------------------------------------------------- /tests/exit.sh: -------------------------------------------------------------------------------- 1 | F1() 2 | { 3 | echo 'I like bash programming' 4 | exit 0 5 | } 6 | 7 | 8 | F1 -------------------------------------------------------------------------------- /tests/for5.sh: -------------------------------------------------------------------------------- 1 | for (( ; ; )) 2 | do 3 | echo "infinite loops" 4 | break 5 | done 6 | -------------------------------------------------------------------------------- /tests/lower0.sh: -------------------------------------------------------------------------------- 1 | name='Fahmida' 2 | echo "$name ?" 3 | echo ${name,} 4 | echo ${name,,} 5 | -------------------------------------------------------------------------------- /gperf.sh: -------------------------------------------------------------------------------- 1 | LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libprofiler.so \ 2 | CPUPROFILE=prof.out $1 3 | -------------------------------------------------------------------------------- /tests/for2.sh: -------------------------------------------------------------------------------- 1 | for day in Mon Tue Wed Thu Fri 2 | do 3 | echo "Weekday $((i++)) : $day" 4 | done -------------------------------------------------------------------------------- /tests/sushell: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | [ -z "$SUSHELL" ] && SUSHELL=/bin/sh 4 | 5 | exec $SUSHELL 6 | -------------------------------------------------------------------------------- /tests/redirection0.sh: -------------------------------------------------------------------------------- 1 | rm -rf gen/res.txt 2 | var="tests" 3 | ls $var > gen/res.txt 4 | cat gen/res.txt 5 | -------------------------------------------------------------------------------- /tests/if5.sh: -------------------------------------------------------------------------------- 1 | n=15 2 | if [[ $n -eq 15 || $n -eq 45 ]] 3 | then 4 | echo "You won" 5 | else 6 | echo "You lost!" 7 | fi 8 | -------------------------------------------------------------------------------- /tests/devpts: -------------------------------------------------------------------------------- 1 | # GID of the `tty' group 2 | TTYGRP=5 3 | 4 | # Set to 600 to have `mesg n' be the default 5 | TTYMODE=620 6 | -------------------------------------------------------------------------------- /tests/for6.sh: -------------------------------------------------------------------------------- 1 | FILES="file1 2 | /path/to/file2 3 | /etc/resolv.conf" 4 | for f in $FILES 5 | do 6 | echo "Processing $f" 7 | done 8 | -------------------------------------------------------------------------------- /tests/pipeline0.sh: -------------------------------------------------------------------------------- 1 | if ! cat /proc/filesystems | tail -n 1 | grep "^sysfs" >> /dev/null; then 2 | echo "sysfs not supported" 3 | fi -------------------------------------------------------------------------------- /tests/redir.sh: -------------------------------------------------------------------------------- 1 | RANDOM_SEED_FILE="tests/random-seed" 2 | ( date +%s.%N; [ -f "$RANDOM_SEED_FILE" ] && cat "$RANDOM_SEED_FILE" ) 3 | -------------------------------------------------------------------------------- /gprof.sh: -------------------------------------------------------------------------------- 1 | gprof $1 gmon.out > main.gprof 2 | gprof2dot < main.gprof | dot -Tsvg -o output.svg 3 | gprof -b $1 gmon.out > output.txt 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "bash-parser"] 2 | path = bash-parser 3 | url = https://github.com/franksinankaya/bash-parser.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /tests/for8.sh: -------------------------------------------------------------------------------- 1 | NUMBERS="9 7 3 8 37.53" 2 | 3 | for number in `echo $NUMBERS` # for number in 9 7 3 8 37.53 4 | do 5 | echo -n "$number " 6 | done 7 | -------------------------------------------------------------------------------- /tests/functions1.sh: -------------------------------------------------------------------------------- 1 | testecho() 2 | ( 3 | time="/bin/date" 4 | d=$(${time}) 5 | echo $d 6 | echo "hello world" 7 | ) 8 | 9 | testecho 10 | 11 | -------------------------------------------------------------------------------- /tests/perf.text: -------------------------------------------------------------------------------- 1 | 0.018 2 | 0.023 3 | 0.009 4 | 0.012 5 | 0.183 6 | 0.030 7 | 0.012 8 | 0.009 9 | 10 | case0 11 | complete 12 | if8 13 | complete 14 | -------------------------------------------------------------------------------- /tests/local.sh: -------------------------------------------------------------------------------- 1 | test() { 2 | local a=5 3 | echo $a 4 | 5 | local b 6 | b=4 7 | } 8 | 9 | b="bbb" 10 | a=4 11 | test 12 | echo $a 13 | echo $b 14 | -------------------------------------------------------------------------------- /tests/until.sh: -------------------------------------------------------------------------------- 1 | counter=0 2 | 3 | until [ $counter -gt 5 ] 4 | do 5 | echo Counter: $counter 6 | counter=$((counter + 1)) 7 | # ((counter++)) 8 | done 9 | -------------------------------------------------------------------------------- /tests/2.1.sh: -------------------------------------------------------------------------------- 1 | # Cleanup 2 | # Run as root, of course. 3 | 4 | cd /var/log 5 | cat /dev/null > messages 6 | cat /dev/null > wtmp 7 | echo "Log files cleaned up." 8 | -------------------------------------------------------------------------------- /tests/arguments.sh: -------------------------------------------------------------------------------- 1 | echo "Argument one is ${1}" 2 | echo "Argument two is ${2}" 3 | echo "Argument three is ${3}" 4 | echo "Arguments are ${@}" 5 | echo "Arguments are ${#}" 6 | -------------------------------------------------------------------------------- /tests/env3.sh: -------------------------------------------------------------------------------- 1 | test () { 2 | if ! cat tests/fstab >> /dev/null; then 3 | echo "cat tests" 4 | return 1 5 | fi 6 | return 0 7 | } 8 | test 9 | echo $? 10 | 11 | -------------------------------------------------------------------------------- /tests/if10.sh: -------------------------------------------------------------------------------- 1 | var1=5 2 | var2=4 3 | if (( var1 > var2 )) 4 | then #^ ^ Note: Not $var1, $var2. Why? 5 | echo "$var1 is greater than $var2" 6 | fi # 5 is greater than 4 7 | # exit 0 8 | -------------------------------------------------------------------------------- /tests/hostname0.sh: -------------------------------------------------------------------------------- 1 | HOSTNAME=$(/bin/hostname) 2 | if [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" -o ! -z "`echo $HOSTNAME | sed -n '/^[0-9]*\.[0-9].*/p'`" ] ; then 3 | hostname localhost 4 | fi 5 | -------------------------------------------------------------------------------- /tests/if4.sh: -------------------------------------------------------------------------------- 1 | String='' # Zero-length ("null") string variable. 2 | if [ -z "$String" ] 3 | then 4 | echo "String is null." 5 | else 6 | echo "String is NOT null." 7 | fi # $String is null. 8 | -------------------------------------------------------------------------------- /tests/for7.sh: -------------------------------------------------------------------------------- 1 | DB_AWS_ZONE=('us-east-2a' 'us-west-1a' 'eu-central-1a') 2 | for zone in "${DB_AWS_ZONE[@]}" 3 | do 4 | echo "Creating rds (DB) server in $zone, please wait ..." 5 | done 6 | 7 | a=4 8 | -------------------------------------------------------------------------------- /tests/while0.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | input="./tests/fstab" 3 | while read device mountpt fstype options 4 | do 5 | echo "device=$device mountpt=$mountpt fstype=$fstype options=$options" 6 | done < "$input" 7 | -------------------------------------------------------------------------------- /tests/lower.sh: -------------------------------------------------------------------------------- 1 | lower() { 2 | # Usage: lower "string" 3 | printf '%s\n' "${1,,}" 4 | } 5 | 6 | lower "HELLO" 7 | # hello 8 | 9 | lower "HeLlO" 10 | # hello 11 | 12 | lower "hello" 13 | # hello -------------------------------------------------------------------------------- /tests/upper.sh: -------------------------------------------------------------------------------- 1 | upper() { 2 | # Usage: upper "string" 3 | printf '%s\n' "${1^^}" 4 | } 5 | 6 | upper "hello" 7 | # HELLO 8 | 9 | upper "HeLlO" 10 | # HELLO 11 | 12 | upper "HELLO" 13 | # HELLO 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "lib": ["es6"], 6 | "sourceMap": true 7 | }, 8 | "exclude": [ 9 | "node_modules" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tests/for1.sh: -------------------------------------------------------------------------------- 1 | array=('klk' 'ioioi' 'tj') 2 | 3 | for item in ${array[*]}; do 4 | echo ${item} 5 | done 6 | 7 | # Echo array 8 | array=('klk' 'ioioi' 'tj') 9 | for item in ${array[@]}; do 10 | echo ${item} 11 | done 12 | -------------------------------------------------------------------------------- /tests/if1.sh: -------------------------------------------------------------------------------- 1 | v=0 2 | v=0 3 | v=0 4 | v=0 5 | v=0 6 | v=0 7 | v=0 8 | v=0 9 | v=0 10 | v=0 11 | v=0 12 | v=0 13 | v=0 14 | v=0 15 | v=0 16 | v=0 17 | v=0 18 | v=0 19 | v=0 20 | v=0 21 | v=0 22 | if [ $v -eq 0 ]; then 23 | echo "hello" 24 | fi 25 | -------------------------------------------------------------------------------- /tests/showsize.sh: -------------------------------------------------------------------------------- 1 | DF="/bin/df -h" 2 | AWK="/usr/bin/awk" 3 | 4 | show_size() { 5 | local used=$($DF "$1" | $AWK '/^\//{print $3}') 6 | local total=$($DF "$1" | $AWK '/^\//{print $2}') 7 | echo ""$1": $used/$total used" 8 | } 9 | 10 | show_size /dev/sda 11 | -------------------------------------------------------------------------------- /tests/for4.sh: -------------------------------------------------------------------------------- 1 | for (( c=1; c<=5; c++ )) 2 | do 3 | echo "Welcome $c times" 4 | done 5 | 6 | for (( counter=10; counter>0; counter-- )) 7 | do 8 | echo "$counter" 9 | done 10 | 11 | for (( counter=1; counter<=10; counter++ )) 12 | do 13 | echo "$counter" 14 | done 15 | 16 | -------------------------------------------------------------------------------- /tests/array.sh: -------------------------------------------------------------------------------- 1 | array=('value1' 'value2' 'value3' 'value4') 2 | 3 | echo "Array's length is ${#array[@]}" 4 | echo "Array's first value is ${array[0]}" 5 | echo "Array's second value is ${array[1]}" 6 | echo "Array's three value is ${array[3]}" 7 | echo "Array's full values are ${array[@]}" 8 | -------------------------------------------------------------------------------- /tests/for3.sh: -------------------------------------------------------------------------------- 1 | for flag in `awk -v dir=$dir '{ if ($2 == dir) { print "FOUND"; split($4,FLAGS,",") } }; \ 2 | END { for (f in FLAGS) print FLAGS[f] }' < /proc/mounts`; do 3 | [ "$flag" = "FOUND" ] && partition="read-write" 4 | [ "$flag" = "ro" ] && { partition="read-only"; break; } 5 | done 6 | -------------------------------------------------------------------------------- /tests/readfile.sh: -------------------------------------------------------------------------------- 1 | file_data="$(<"file")" 2 | 3 | # Bash <4 (discarding empty lines). 4 | IFS=$'\n' read -d "" -ra file_data < "file" 5 | 6 | # Bash <4 (preserving empty lines). 7 | while read -r line; do 8 | file_data+=("$line") 9 | done < "file" 10 | 11 | # Bash 4+ 12 | mapfile -t file_data < "file" 13 | -------------------------------------------------------------------------------- /tests/if3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "$PWD" 4 | LOG_DIR="$PWD/gen" 5 | cd "$LOG_DIR" 6 | echo "LOG_DIR=$LOG_DIR" 7 | echo "PWD=$PWD" 8 | if [ "$PWD" == "$LOG_DIR" ]; 9 | then 10 | echo "directory changed to $LOG_DIR" 11 | cd .. 12 | else 13 | echo "Can't change to $LOG_DIR vs. $PWD ." 14 | cd .. 15 | fi 16 | -------------------------------------------------------------------------------- /tests/alignment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: alignment 4 | # Required-Start: mountkernfs 5 | # Required-Stop: mountkernfs 6 | # Default-Start: S 7 | # Default-Stop: 8 | ### END INIT INFO 9 | 10 | if [ -e /proc/cpu/alignment ]; then 11 | echo "3" > /proc/cpu/alignment 12 | fi 13 | 14 | -------------------------------------------------------------------------------- /tests/functions3.sh: -------------------------------------------------------------------------------- 1 | in_func() 2 | { 3 | echo "$1" "$2" 4 | } 5 | 6 | # Offline memory sections from ${1} to ${2} 7 | # Return 0 on success and 1 on failure 8 | func() 9 | { 10 | echo $1 $2 11 | for ((i = ${1}; i <= ${2}; i++)); do 12 | in_func ${1} $(($i - 1)) 13 | echo $1 $2 14 | done 15 | } 16 | 17 | 18 | func 1 10 19 | -------------------------------------------------------------------------------- /tests/reboot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: reboot 4 | # Required-Start: 5 | # Required-Stop: 6 | # Default-Start: 7 | # Default-Stop: 6 8 | # Short-Description: Execute the reboot command. 9 | # Description: 10 | ### END INIT INFO 11 | 12 | PATH=/sbin:/bin:/usr/sbin:/usr/bin 13 | 14 | echo -n "Rebooting... " 15 | reboot SED_HALTARGS 16 | -------------------------------------------------------------------------------- /tests/functions0.sh: -------------------------------------------------------------------------------- 1 | Rectangle_Area() { 2 | area=$(($1 * $2)) 3 | echo "Area is : $area" 4 | } 5 | 6 | Rectangle_Area 10 20 7 | 8 | greeting() { 9 | 10 | str="Hello, $name" 11 | echo $str 12 | 13 | } 14 | 15 | F1() 16 | { 17 | echo 'I like bash programming' 18 | } 19 | 20 | 21 | giveMeAString() { 22 | echo "Some result" 23 | } 24 | 25 | result=$(giveMeAString) 26 | echo $result 27 | 28 | -------------------------------------------------------------------------------- /tests/redirect.sh: -------------------------------------------------------------------------------- 1 | RANDOM_SEED_FILE=./gen/random-seed 2 | dd if=/dev/urandom of=$RANDOM_SEED_FILE count=1 \ 3 | >/dev/null 2>&1 || echo "urandom start: failed." 4 | 5 | echo "urandom started" 6 | 7 | rm ./gen/urandom 8 | 9 | ( date +%s.%N; [ -f "$RANDOM_SEED_FILE" ] && cat "$RANDOM_SEED_FILE" ) \ 10 | >./gen/urandom 11 | 12 | if [ -f "./gen/urandom" ]; then 13 | echo "./gen/urandom generated" 14 | fi -------------------------------------------------------------------------------- /tests/dmesg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: dmesg 4 | # Required-Start: 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | ### END INIT INFO 9 | 10 | if [ -f /var/log/dmesg ]; then 11 | if LOGPATH=$(which logrotate); then 12 | $LOGPATH -f /etc/logrotate-dmesg.conf 13 | else 14 | mv -f /var/log/dmesg /var/log/dmesg.old 15 | fi 16 | fi 17 | dmesg -s 131072 > /var/log/dmesg 18 | -------------------------------------------------------------------------------- /tests/array0.sh: -------------------------------------------------------------------------------- 1 | # As mentioned in man bash: 2 | # If the word is double-quoted, ${name[*]} expands to a single word 3 | # with the value of each array member separated by the first character 4 | # of the IFS special variable, and ${name[@]} expands each element of 5 | # name to a separate word. 6 | 7 | # Examples: 8 | 9 | IFS="," 10 | array=("1" "2" "3") 11 | echo "${array[*]}" 12 | # '1 2 3' 13 | echo "${array[@]}" 14 | # '1''2''3' 15 | 16 | -------------------------------------------------------------------------------- /tests/3.1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Reading lines in /etc/fstab. 3 | 4 | File=/etc/fstab 5 | 6 | { 7 | read line1 8 | read line2 9 | } < $File 10 | 11 | echo "First line in $File is:" 12 | echo "$line1" 13 | echo 14 | echo "Second line in $File is:" 15 | echo "$line2" 16 | 17 | exit 0 18 | 19 | # Now, how do you parse the separate fields of each line? 20 | # Hint: use awk, or . . . 21 | # . . . Hans-Joerg Diers suggests using the "set" Bash builtin. -------------------------------------------------------------------------------- /tests/if9.sh: -------------------------------------------------------------------------------- 1 | if [ -f /etc/hostname ];then 2 | echo "hostname `cat /etc/hostname`" 3 | # elif [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" -o ! -z "`echo $HOSTNAME | sed -n '/^[0-9]*\.[0-9].*/p'`" ] ; then 4 | # echo "hostname localhost" 5 | fi 6 | 7 | if [ -f /etc/hostname ];then 8 | echo "hostname `cat /etc/hostname`" 9 | elif [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" -o ! -z "`echo $HOSTNAME`" ] ; then 10 | echo "hostname localhost" 11 | fi 12 | -------------------------------------------------------------------------------- /tests/9.9.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo $_ # /bin/bash 4 | # Just called /bin/bash to run the script. 5 | # Note that this will vary according to 6 | #+ how the script is invoked. 7 | 8 | du >/dev/null # So no output from command. 9 | echo $_ # du 10 | 11 | ls -al >/dev/null # So no output from command. 12 | echo $_ # -al (last argument) 13 | 14 | : 15 | echo $_ # : -------------------------------------------------------------------------------- /tests/braceexpansion.sh: -------------------------------------------------------------------------------- 1 | # Nesting. 2 | # echo {A..Z}{0..9} 3 | 4 | # Syntax: {..} 5 | 6 | # Print numbers 1-100. 7 | echo {1..100} 8 | 9 | # Print range of floats. 10 | # echo 1.{1..9} 11 | 12 | # Print chars a-z. 13 | echo {a..z} 14 | echo {A..Z} 15 | 16 | 17 | # Print zero-padded numbers. 18 | # CAVEAT: bash 4+ 19 | # echo {01..100} 20 | 21 | # Change increment amount. 22 | # Syntax: {....} 23 | # CAVEAT: bash 4+ 24 | echo {1..10..2} # Increment by 2. 25 | -------------------------------------------------------------------------------- /tests/save-rtc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: save-rtc 4 | # Required-Start: 5 | # Required-Stop: $local_fs hwclock 6 | # Default-Start: S 7 | # Default-Stop: 0 6 8 | # Short-Description: Store system clock into file 9 | # Description: 10 | ### END INIT INFO 11 | 12 | TIMESTAMP_FILE=/etc/timestamp 13 | 14 | [ -f /etc/default/timestamp ] && . /etc/default/timestamp 15 | 16 | # Update the timestamp 17 | date -u +%4Y%2m%2d%2H%2M%2S 2>/dev/null > "$TIMESTAMP_FILE" 18 | -------------------------------------------------------------------------------- /tests/split.sh: -------------------------------------------------------------------------------- 1 | split() { 2 | # Usage: split "string" "delimiter" 3 | IFS=$'\n' read -d "" -ra arr <<< "${1//$2/$'\n'}" 4 | printf '%s\n' "${arr[@]}" 5 | } 6 | 7 | split "apples,oranges,pears,grapes" "," 8 | # apples 9 | # oranges 10 | # pears 11 | # grapes 12 | 13 | split "1, 2, 3, 4, 5" ", " 14 | # 1 15 | # 2 16 | # 3 17 | # 4 18 | # 5 19 | 20 | # Multi char delimiters work too! 21 | split "hello---world---my---name---is---john" "---" 22 | # hello 23 | # world 24 | # my 25 | # name 26 | # is 27 | # john -------------------------------------------------------------------------------- /tests/9.4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # t-out.sh [time-out] 3 | # Inspired by a suggestion from "syngin seven" (thanks). 4 | 5 | 6 | TIMELIMIT=4 # 4 seconds 7 | 8 | read -t $TIMELIMIT variable <&1 9 | # ^^^ 10 | # In this instance, "<&1" is needed for Bash 1.x and 2.x, 11 | # but unnecessary for Bash 3+. 12 | 13 | echo 14 | 15 | if [ -z "$variable" ] # Is null? 16 | then 17 | echo "Timed out, variable still unset." 18 | else 19 | echo "variable = $variable" 20 | fi 21 | 22 | exit 0 -------------------------------------------------------------------------------- /tests/parameterexpansion.sh: -------------------------------------------------------------------------------- 1 | string=01234567890abcdefgh 2 | path=${string}ij 3 | 4 | TEXT=scripting_for_phun 5 | echo ${TEXT:10:3} 6 | echo ${TEXT:10} 7 | 8 | Str="Learn Bash Commands from UbuntuPit" 9 | subStr=${Str:0:20} 10 | echo $subStr 11 | 12 | Str="Learn Linux from LinuxHint" 13 | subStr=${Str:6:5} 14 | echo $subStr 15 | 16 | string=01234567890abcdefgh 17 | echo ${string:7} 18 | echo ${string:7:2} 19 | echo ${string:7:-2} 20 | echo ${string: -7} 21 | echo ${string: -7:2} 22 | 23 | path=${string}ij 24 | echo $path 25 | -------------------------------------------------------------------------------- /tests/sendsigs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: sendsigs 4 | # Required-Start: 5 | # Required-Stop: umountnfs 6 | # Default-Start: 7 | # Default-Stop: 0 6 8 | # Short-Description: Kill all remaining processes. 9 | # Description: 10 | ### END INIT INFO 11 | 12 | PATH=/sbin:/bin:/usr/sbin:/usr/bin 13 | 14 | # Kill all processes. 15 | echo "Sending all processes the TERM signal..." 16 | killall5 -15 17 | sleep 5 18 | echo "Sending all processes the KILL signal..." 19 | killall5 -9 20 | 21 | : exit 0 22 | -------------------------------------------------------------------------------- /tests/conditionals.sh: -------------------------------------------------------------------------------- 1 | ! [[ 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no 2 | 3 | [[ ! 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no 4 | 5 | ! [[ 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no 6 | 7 | 8 | [ "$ROOTFS_READ_ONLY" = "no" ] || echo 1 9 | [ "$ROOTFS_READ_ONLY" = "no" ] && echo 0 10 | 11 | [ -f /etc/default/urandom ] && . /etc/default/urandom 12 | 13 | test -c /dev/urandom || echo 0 14 | 15 | # 16 | # Create multiplexor device. 17 | # 18 | test -c /dev/ptmx || echo "ptmx device does not exist" 19 | 20 | [ -x /sbin/swapon ] && echo "swap on is executable" 21 | -------------------------------------------------------------------------------- /tests/redirection.sh: -------------------------------------------------------------------------------- 1 | # dmesg -s 131072 > gen/dmesg 2 | 3 | echo "Learning Laravel 5"> gen/book.txt 4 | echo "Learning Laravel 6">> gen/book.txt 5 | 6 | cat gen/book.txt 7 | 8 | echo "hello world" > gen/messages 9 | echo "hello world" > gen/wtmp 10 | 11 | cat /dev/null > gen/messages 12 | cat /dev/null > gen/wtmp 13 | 14 | if [ -s gen/messages ]; 15 | then 16 | echo "gen/messages has content" 17 | else 18 | echo "gen/messages empty" 19 | fi 20 | 21 | if [ -s gen/wtmp ]; 22 | then 23 | echo "gen/wtmp has content" 24 | else 25 | echo "gen/wtmp empty" 26 | fi 27 | -------------------------------------------------------------------------------- /tests/2.2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Proper header for a Bash script. 3 | 4 | # Cleanup, version 2 5 | 6 | # Run as root, of course. 7 | # Insert code here to print error message and exit if not root. 8 | 9 | LOG_DIR=/var/log 10 | # Variables are better than hard-coded values. 11 | cd $LOG_DIR 12 | 13 | cat /dev/null > messages 14 | cat /dev/null > wtmp 15 | 16 | 17 | echo "Logs cleaned up." 18 | 19 | exit # The right and proper method of "exiting" from a script. 20 | # A bare "exit" (no parameter) returns the exit status 21 | #+ of the preceding command. 22 | -------------------------------------------------------------------------------- /tests/6.1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo hello 4 | echo $? # Exit status 0 returned because command executed successfully. 5 | 6 | lskdf # Unrecognized command. 7 | echo $? # Non-zero exit status returned -- command failed to execute. 8 | 9 | echo 10 | 11 | exit 113 # Will return 113 to shell. 12 | # To verify this, type "echo $?" after script terminates. 13 | 14 | # By convention, an 'exit 0' indicates success, 15 | #+ while a non-zero exit value means an error or anomalous condition. 16 | # See the "Exit Codes With Special Meanings" appendix. 17 | -------------------------------------------------------------------------------- /tests/if6.sh: -------------------------------------------------------------------------------- 1 | if [ -e /sys ] && grep -q sysfs /proc/filesystems && ! [ -e /sys/class ]; then 2 | echo "mounting" 3 | fi 4 | 5 | if grep -q sysfs /proc/filesystems; then 6 | echo "sysfs supported" 7 | fi 8 | 9 | if [ -e /sys ]; then 10 | echo "sysfs exists" 11 | fi 12 | 13 | if ! [ -e /sys/class ]; then 14 | echo "sysfs class not supported" 15 | else 16 | echo "sysfs class supported" 17 | fi 18 | 19 | # 20 | # Mount /dev/pts if needed. 21 | # 22 | if ! grep -q devpts /proc/mounts 23 | then 24 | echo "devpts not mounted" 25 | else 26 | echo "devpts mounted" 27 | fi 28 | -------------------------------------------------------------------------------- /tests/if8.sh: -------------------------------------------------------------------------------- 1 | # -z option will test that string length is zero. 2 | if [ -z "" ]; then 3 | echo "length of the string is zero" 4 | fi 5 | 6 | # -n option will test that string length is nonzero. 7 | if [ -n "hoot" ]; then 8 | echo "length of the sting is nonzero" 9 | fi 10 | 11 | # ! option will negate boolean result. 12 | if [ ! -z "hoot" ]; then 13 | echo "boolean expression is negated to true even string length check returns false" 14 | fi 15 | 16 | # -d option is used to test if file is a directory. 17 | if [ -d . ]; then 18 | echo ". is a directory" 19 | fi 20 | -------------------------------------------------------------------------------- /tests/replacement.sh: -------------------------------------------------------------------------------- 1 | ${VAR#PATTERN} Remove shortest match of pattern from start of string. 2 | ${VAR##PATTERN} Remove longest match of pattern from start of string. 3 | ${VAR%PATTERN} Remove shortest match of pattern from end of string. 4 | ${VAR%%PATTERN} Remove longest match of pattern from end of string. 5 | ${VAR/PATTERN/REPLACE} Replace first match with string. 6 | ${VAR//PATTERN/REPLACE} Replace all matches with string. 7 | ${VAR/PATTERN} Remove first match. 8 | ${VAR//PATTERN} Remove all matches. 9 | 10 | ${#VAR} Length of var in characters. 11 | ${#ARR[@]} Length of array in elements. 12 | -------------------------------------------------------------------------------- /tests/banner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: banner 4 | # Required-Start: 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | ### END INIT INFO 9 | 10 | if [ ! -e /dev/tty ]; then 11 | /bin/mknod -m 0666 /dev/tty c 5 0 12 | fi 13 | 14 | if ( > /dev/tty0 ) 2>/dev/null; then 15 | vtmaster=/dev/tty0 16 | elif ( > /dev/vc/0 ) 2>/dev/null; then 17 | vtmaster=/dev/vc/0 18 | elif ( > /dev/console ) 2>/dev/null; then 19 | vtmaster=/dev/console 20 | else 21 | vtmaster=/dev/null 22 | fi 23 | echo > $vtmaster 24 | echo "Please wait: booting..." > $vtmaster 25 | -------------------------------------------------------------------------------- /tests/pipeline.sh: -------------------------------------------------------------------------------- 1 | echo "Hello" | tr 'el' 'x' #Result: Hxxxo 2 | echo "Hello" | tr 'el' 'ay' #Result: Hayyo 3 | 4 | echo "Hello world and good day." | cut -d " " -f 1 #Result: Hello 5 | echo "Hello-world-and-good-day." | cut -d "-" -f 2 #Result: world 6 | 7 | echo "Hello" | tr '[:lower:]' '[:upper:]' #Result: HELLO 8 | echo "Hello" | tr '[:upper:]' '[:lower:]' #Result: hello 9 | 10 | echo "Hello" | tr -d "el" #Result: Ho 11 | 12 | echo "The quick brown fox" | sed 's/brown/red/' #Result: The quick red fox 13 | 14 | echo "Hello, hello, hello" | sed 's/hello/goodbye/' #Result: Hello, goodbye, hello 15 | 16 | dmesg | head -n 10 -------------------------------------------------------------------------------- /tests/halt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: halt 4 | # Required-Start: 5 | # Required-Stop: 6 | # Default-Start: 7 | # Default-Stop: 0 8 | # Short-Description: Execute the halt command. 9 | # Description: 10 | ### END INIT INFO 11 | 12 | PATH=/sbin:/bin:/usr/sbin:/usr/bin 13 | 14 | # See if we need to cut the power. 15 | if test -x /etc/init.d/ups-monitor 16 | then 17 | /etc/init.d/ups-monitor poweroff 18 | fi 19 | 20 | # Don't shut down drives if we're using RAID. 21 | hddown="-h" 22 | if grep -qs '^md.*active' /proc/mdstat 23 | then 24 | hddown="" 25 | fi 26 | 27 | halt SED_HALTARGS -p $hddown 28 | 29 | : exit 0 30 | -------------------------------------------------------------------------------- /tests/umountfs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: umountfs 4 | # Required-Start: 5 | # Required-Stop: 6 | # Default-Start: 7 | # Default-Stop: 0 6 8 | # Short-Description: Turn off swap and unmount all local file systems. 9 | # Description: 10 | ### END INIT INFO 11 | 12 | PATH=/sbin:/bin:/usr/sbin:/usr/bin 13 | 14 | echo "Deactivating swap..." 15 | [ -x /sbin/swapoff ] && swapoff -a 16 | 17 | # We leave /proc mounted. 18 | echo "Unmounting local filesystems..." 19 | grep -q /mnt/ram /proc/mounts && mount -o remount,ro /mnt/ram 20 | mount -o remount,ro / 21 | 22 | umount -f -a -r > /dev/null 2>&1 23 | 24 | : exit 0 25 | -------------------------------------------------------------------------------- /tests/devpts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: devpts 4 | # Required-Start: udev 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | # Short-Description: Mount /dev/pts file systems. 9 | ### END INIT INFO 10 | 11 | . /etc/default/devpts 12 | 13 | if grep -q devpts /proc/filesystems 14 | then 15 | # 16 | # Create multiplexor device. 17 | # 18 | test -c /dev/ptmx || mknod -m 666 /dev/ptmx c 5 2 19 | 20 | # 21 | # Mount /dev/pts if needed. 22 | # 23 | if ! grep -q devpts /proc/mounts 24 | then 25 | mkdir -p /dev/pts 26 | mount -t devpts devpts /dev/pts -ogid=${TTYGRP},mode=${TTYMODE} 27 | fi 28 | fi 29 | -------------------------------------------------------------------------------- /tests/for.sh: -------------------------------------------------------------------------------- 1 | for day in Mon Tue Wed Thu Fri 2 | do 3 | echo "Weekday : $day" 4 | done 5 | 6 | FILES=/path/to/* 7 | for f in $FILES 8 | do 9 | echo "Processing $f file..." 10 | ##take action on each file. $f store current file name 11 | echo $f 12 | done 13 | 14 | for file in /etc/* 15 | do 16 | if [ "${file}" == "/etc/resolv.conf" ] 17 | then 18 | countNameservers=$(grep -c nameserver /etc/resolv.conf) 19 | echo "Total ${countNameservers} nameservers defined in ${file}" 20 | break 21 | fi 22 | done 23 | 24 | for f in $(ls test/*.sh) 25 | do 26 | print "File $f" 27 | done 28 | 29 | for i in 1 2 3 4 5 30 | do 31 | echo "Welcome $i times" 32 | done 33 | -------------------------------------------------------------------------------- /tests/read.sh: -------------------------------------------------------------------------------- 1 | # while read; do echo "$REPLY"; done 2 | 3 | read first middle last 4 | echo "first=$first" 5 | echo "middle=$middle" 6 | echo "last=$last" 7 | echo "Hello $first $middle $last" 8 | 9 | echo "Enter first number" 10 | read x 11 | echo "Enter second number" 12 | read y 13 | (( sum=x+y )) 14 | echo "The result of addition=$sum" 15 | 16 | 17 | # F1 18 | 19 | # echo "Enter your name" 20 | # read name 21 | 22 | # echo "Enter Your Name" 23 | # read name 24 | # echo "Welcome $name to LinuxHint" 25 | 26 | # echo "Enter username" 27 | # read username 28 | # echo "Enter password" 29 | # read password 30 | 31 | 32 | # echo "Enter your lucky number" 33 | # read n 34 | 35 | -------------------------------------------------------------------------------- /tests/regex.sh: -------------------------------------------------------------------------------- 1 | regex() { 2 | # Usage: regex "string" "regex" 3 | [[ $1 =~ $2 ]] && printf '%s\n' "${BASH_REMATCH[1]}" 4 | } 5 | 6 | regex ' hello' '^\s*(.*)' 7 | # hello 8 | 9 | regex "#FFFFFF" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$' 10 | #FFFFFF 11 | 12 | regex "red" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$' 13 | # no output (invalid) 14 | 15 | is_hex_color() { 16 | if [[ $1 =~ ^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$ ]]; then 17 | printf '%s\n' "${BASH_REMATCH[1]}" 18 | else 19 | printf '%s\n' "error: $1 is an invalid color." 20 | return 1 21 | fi 22 | } 23 | 24 | read -r color 25 | is_hex_color "$color" || color="#FFFFFF" 26 | 27 | -------------------------------------------------------------------------------- /tests/hostname.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: hostname 4 | # Required-Start: 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | # Short-Description: Set hostname based on /etc/hostname 9 | ### END INIT INFO 10 | HOSTNAME=$(/bin/hostname) 11 | 12 | hostname -b -F /etc/hostname 2> /dev/null 13 | if [ $? -eq 0 ]; then 14 | exit 15 | fi 16 | 17 | # Busybox hostname doesn't support -b so we need implement it on our own 18 | if [ -f /etc/hostname ];then 19 | hostname `cat /etc/hostname` 20 | elif [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" -o ! -z "`echo $HOSTNAME | sed -n '/^[0-9]*\.[0-9].*/p'`" ] ; then 21 | hostname localhost 22 | fi 23 | -------------------------------------------------------------------------------- /tests/rmnologin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: rmnologin 4 | # Required-Start: $remote_fs $all 5 | # Required-Stop: 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 8 | # Short-Description: Remove /etc/nologin at boot 9 | # Description: This script removes the /etc/nologin file as the 10 | # last step in the boot process, if DELAYLOGIN=yes. 11 | # If DELAYLOGIN=no, /etc/nologin was not created by 12 | # bootmisc earlier in the boot process. 13 | ### END INIT INFO 14 | 15 | if test -f /etc/nologin.boot 16 | then 17 | rm -f /etc/nologin /etc/nologin.boot 18 | fi 19 | 20 | : exit 0 21 | -------------------------------------------------------------------------------- /tests/single: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: single 4 | # Required-Start: $local_fs $all killprocs 5 | # Required-Stop: 6 | # Default-Start: 1 7 | # Default-Stop: 8 | # Short-Description: executed by init(8) upon entering runlevel 1 (single). 9 | ### END INIT INFO 10 | 11 | PATH="/sbin:/bin:/usr/sbin:/usr/bin" 12 | 13 | # Kill all processes. 14 | echo "Sending all processes the TERM signal..." 15 | killall5 -15 16 | sleep 5 17 | echo "Sending all processes the KILL signal..." 18 | killall5 -9 19 | 20 | # We start update here, since we just killed it. 21 | test -x /sbin/update && update 22 | 23 | echo "Entering single-user mode..." 24 | exec init -t1 S 25 | -------------------------------------------------------------------------------- /tests/9.8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # If $IFS set, but empty, 4 | #+ then "$*" and "$@" do not echo positional params as expected. 5 | 6 | mecho () # Echo positional parameters. 7 | { 8 | echo "$1,$2,$3"; 9 | } 10 | 11 | 12 | IFS="" # Set, but empty. 13 | set a b c # Positional parameters. 14 | 15 | mecho "$*" # abc,, 16 | # ^^ 17 | mecho $* # a,b,c 18 | 19 | mecho $@ # a,b,c 20 | mecho "$@" # a,b,c 21 | 22 | # The behavior of $* and $@ when $IFS is empty depends 23 | #+ on which Bash or sh version being run. 24 | # It is therefore inadvisable to depend on this "feature" in a script. 25 | 26 | 27 | # Thanks, Stephane Chazelas. 28 | 29 | exit -------------------------------------------------------------------------------- /tests/emptyvar.sh: -------------------------------------------------------------------------------- 1 | if [ -r ${FOO} ]; then 2 | echo "foo exists 1" 3 | fi 4 | 5 | if [ -w ${FOO} ]; then 6 | echo "foo exists 1" 7 | fi 8 | 9 | if [ -b ${FOO} ]; then 10 | echo "foo exists 1" 11 | fi 12 | 13 | if [ -c ${FOO} ]; then 14 | echo "foo exists 2" 15 | fi 16 | 17 | if [ -x ${FOO} ]; then 18 | echo "foo exists 3" 19 | fi 20 | 21 | FOO="" 22 | if [ -r ${FOO} ]; then 23 | echo "foo exists 1" 24 | fi 25 | 26 | if [ -w ${FOO} ]; then 27 | echo "foo exists 1" 28 | fi 29 | 30 | if [ -b ${FOO} ]; then 31 | echo "foo exists 1" 32 | fi 33 | 34 | if [ -c ${FOO} ]; then 35 | echo "foo exists 2" 36 | fi 37 | 38 | if [ -x ${FOO} ]; then 39 | echo "foo exists 3" 40 | fi 41 | 42 | -------------------------------------------------------------------------------- /tests/functions2.sh: -------------------------------------------------------------------------------- 1 | pidofproc () { 2 | 3 | # pidof output null when no program is running, so no "2>/dev/null". 4 | pid=`pidof $1` 5 | status=$? 6 | case $status in 7 | 0) 8 | echo $pid 9 | return 0 10 | ;; 11 | 127) 12 | echo "ERROR: command pidof not found" >&2 13 | exit 127 14 | ;; 15 | *) 16 | return $status 17 | ;; 18 | esac 19 | } 20 | 21 | status() { 22 | local pid 23 | if [ "$#" = 0 ]; then 24 | echo "Usage: status {program}" 25 | return 1 26 | fi 27 | pid=`pidofproc $1` 28 | if [ -n "$pid" ]; then 29 | echo "$1 (pid $pid) is running..." 30 | return 0 31 | else 32 | echo "$1 is stopped" 33 | fi 34 | return 3 35 | } 36 | 37 | status python 38 | -------------------------------------------------------------------------------- /tests/4.2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Naked variables 3 | 4 | echo 5 | 6 | # When is a variable "naked", i.e., lacking the '$' in front? 7 | # When it is being assigned, rather than referenced. 8 | 9 | # Assignment 10 | a=879 11 | echo "The value of \"a\" is $a." 12 | 13 | # Assignment using 'let' 14 | let a=16+5 15 | echo "The value of \"a\" is now $a." 16 | 17 | echo 18 | 19 | # In a 'for' loop (really, a type of disguised assignment): 20 | echo -n "Values of \"a\" in the loop are: " 21 | for a in 7 8 9 11 22 | do 23 | echo -n "$a " 24 | done 25 | 26 | echo 27 | echo 28 | 29 | # In a 'read' statement (also a type of assignment): 30 | echo -n "Enter \"a\" " 31 | read a 32 | echo "The value of \"a\" is now $a." 33 | 34 | echo 35 | 36 | exit 0 37 | -------------------------------------------------------------------------------- /tests/9.5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # am-i-root.sh: Am I root or not? 3 | 4 | ROOT_UID=0 # Root has $UID 0. 5 | 6 | if [ "$UID" -eq "$ROOT_UID" ] # Will the real "root" please stand up? 7 | then 8 | echo "You are root." 9 | else 10 | echo "You are just an ordinary user (but mom loves you just the same)." 11 | fi 12 | 13 | exit 0 14 | 15 | 16 | # ============================================================= # 17 | # Code below will not execute, because the script already exited. 18 | 19 | # An alternate method of getting to the root of matters: 20 | 21 | ROOTUSER_NAME=root 22 | 23 | username=`id -nu` # Or... username=`whoami` 24 | if [ "$username" = "$ROOTUSER_NAME" ] 25 | then 26 | echo "Rooty, toot, toot. You are root." 27 | else 28 | echo "You are just a regular fella." 29 | fi -------------------------------------------------------------------------------- /tests/4.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | a=23 # Simple case 4 | echo $a 5 | b=$a 6 | echo $b 7 | 8 | # Now, getting a little bit fancier (command substitution). 9 | 10 | a=`echo Hello!` # Assigns result of 'echo' command to 'a' ... 11 | echo $a 12 | # Note that including an exclamation mark (!) within a 13 | #+ command substitution construct will not work from the command-line, 14 | #+ since this triggers the Bash "history mechanism." 15 | # Inside a script, however, the history functions are disabled by default. 16 | 17 | a=`ls -l` # Assigns result of 'ls -l' command to 'a' 18 | echo $a # Unquoted, however, it removes tabs and newlines. 19 | echo 20 | echo "$a" # The quoted variable preserves whitespace. 21 | # (See the chapter on "Quoting.") 22 | 23 | exit 0 -------------------------------------------------------------------------------- /tests/4.7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # shft.sh: Using 'shift' to step through all the positional parameters. 3 | 4 | # Name this script something like shft.sh, 5 | #+ and invoke it with some parameters. 6 | #+ For example: 7 | # sh shft.sh a b c def 83 barndoor 8 | 9 | until [ -z "$1" ] # Until all parameters used up . . . 10 | do 11 | echo -n "$1 " 12 | shift 13 | done 14 | 15 | echo # Extra linefeed. 16 | 17 | # But, what happens to the "used-up" parameters? 18 | echo "$2" 19 | # Nothing echoes! 20 | # When $2 shifts into $1 (and there is no $3 to shift into $2) 21 | #+ then $2 remains empty. 22 | # So, it is not a parameter *copy*, but a *move*. 23 | 24 | exit 25 | 26 | # See also the echo-params.sh script for a "shiftless" 27 | #+ alternative method of stepping through the positional params. 28 | -------------------------------------------------------------------------------- /tests/7.5.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | 4 | a=4 5 | b=5 6 | 7 | # Here "a" and "b" can be treated either as integers or strings. 8 | # There is some blurring between the arithmetic and string comparisons, 9 | #+ since Bash variables are not strongly typed. 10 | 11 | # Bash permits integer operations and comparisons on variables 12 | #+ whose value consists of all-integer characters. 13 | # Caution advised, however. 14 | 15 | echo 16 | 17 | if [ "$a" -ne "$b" ] 18 | then 19 | echo "$a is not equal to $b" 20 | echo "(arithmetic comparison)" 21 | fi 22 | 23 | echo 24 | 25 | if [ "$a" != "$b" ] 26 | then 27 | echo "$a is not equal to $b." 28 | echo "(string comparison)" 29 | # "4" != "5" 30 | # ASCII 52 != ASCII 53 31 | fi 32 | 33 | # In this particular instance, both "-ne" and "!=" work. 34 | 35 | echo 36 | 37 | exit 0 -------------------------------------------------------------------------------- /tests/umountnfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: umountnfs 4 | # Required-Start: 5 | # Required-Stop: umountfs 6 | # Should-Stop: $network $portmap 7 | # Default-Start: 8 | # Default-Stop: 0 6 9 | # Short-Description: Unmount all network filesystems 10 | ### END INIT INFO 11 | 12 | PATH=/sbin:/bin:/usr/sbin:/usr/bin 13 | 14 | # Write a reboot record to /var/log/wtmp before unmounting 15 | halt -w 16 | 17 | echo "Unmounting remote filesystems..." 18 | 19 | test -f /etc/fstab && ( 20 | 21 | # 22 | # Read through fstab line by line and unount network file systems 23 | # 24 | while read device mountpt fstype options 25 | do 26 | if test "$fstype" = nfs || test "$fstype" = smbfs || test "$fstype" = ncpfs || test "$fstype" = cifs 27 | then 28 | umount -f $mountpt 29 | fi 30 | done 31 | ) < /etc/fstab 32 | 33 | : exit 0 34 | -------------------------------------------------------------------------------- /tests/arithmetic.sh: -------------------------------------------------------------------------------- 1 | ((sum=25+35)) 2 | echo $sum 3 | 4 | (( b += 3 )) 5 | echo $b 6 | (( b = b + 1 )) 7 | echo $b 8 | 9 | echo $(( 20 + 5 )) 10 | echo $(( 20 - 5 )) 11 | echo $(( 20 / 5 )) 12 | echo $(( 20 * 5 )) 13 | echo $(( 20 % 3 )) 14 | x=5 15 | # echo $(( x++ )) 16 | echo $x 17 | # echo $(( x++ )) 18 | 19 | x=5 20 | # echo $(( x-- )) 21 | x=2 22 | y=3 23 | # echo $(( x ** y )) 24 | a=$(( 4 - 5 )) 25 | a=$(( 4 / 5 )) 26 | a=$(( 4 * 5 )) 27 | a=$(( 4 + 5 )) 28 | echo $a # 9 29 | a=$((3+5)) 30 | 31 | echo $a # 8 32 | b=$(( a + 3 )) 33 | echo $b # 11 34 | b=$(( $a + 4 )) 35 | echo $b # 12 36 | (( b++ )) 37 | echo $b # 13 38 | (( b += 3 )) 39 | echo $b # 16 40 | a=$(( 4 * 5 )) 41 | echo $a # 20 42 | 43 | value=$(echo "$a") 44 | value=$(echo "$a") 45 | value=$(echo "$a") 46 | value=$(echo "$a") 47 | value=$(echo $a) 48 | value=$(echo 4) 49 | 50 | b=$(( $a + 4 )) 51 | a=$(( 4 + 5 )) 52 | 53 | -------------------------------------------------------------------------------- /tests/files.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | std::vector globVector(const std::string& pattern){ 9 | glob_t glob_result; 10 | glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result); 11 | std::vector files; 12 | for(unsigned int i=0;i files = globVector("tests/*.sh"); 26 | for (const auto & entry : files) 27 | std::cout << entry << std::endl; 28 | } -------------------------------------------------------------------------------- /tests/4.6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ex18.sh 3 | 4 | # Does a 'whois domain-name' lookup on any of 3 alternate servers: 5 | # ripe.net, cw.net, radb.net 6 | 7 | # Place this script -- renamed 'wh' -- in /usr/local/bin 8 | 9 | # Requires symbolic links: 10 | # ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe 11 | # ln -s /usr/local/bin/wh /usr/local/bin/wh-apnic 12 | # ln -s /usr/local/bin/wh /usr/local/bin/wh-tucows 13 | 14 | E_NOARGS=75 15 | 16 | 17 | if [ -z "$1" ] 18 | then 19 | echo "Usage: `basename $0` [domain-name]" 20 | exit $E_NOARGS 21 | fi 22 | 23 | # Check script name and call proper server. 24 | case `basename $0` in # Or: case ${0##*/} in 25 | "wh" ) whois $1@whois.tucows.com;; 26 | "wh-ripe" ) whois $1@whois.ripe.net;; 27 | "wh-apnic" ) whois $1@whois.apnic.net;; 28 | "wh-cw" ) whois $1@whois.cw.net;; 29 | * ) echo "Usage: `basename $0` [domain-name]";; 30 | esac 31 | 32 | exit $? 33 | -------------------------------------------------------------------------------- /tests/dirname.sh: -------------------------------------------------------------------------------- 1 | dirname() { 2 | # Usage: dirname "path" 3 | local tmp=${1:-.} 4 | 5 | [[ $tmp != *[!/]* ]] && { 6 | printf '/\n' 7 | return 8 | } 9 | 10 | tmp=${tmp%%"${tmp##*[!/]}"} 11 | 12 | [[ $tmp != */* ]] && { 13 | printf '.\n' 14 | return 15 | } 16 | 17 | tmp=${tmp%/*} 18 | tmp=${tmp%%"${tmp##*[!/]}"} 19 | 20 | printf '%s\n' "${tmp:-/}" 21 | } 22 | 23 | basename() { 24 | # Usage: basename "path" ["suffix"] 25 | local tmp 26 | 27 | tmp=${1%"${1##*[!/]}"} 28 | tmp=${tmp##*/} 29 | tmp=${tmp%"${2/"$tmp"}"} 30 | 31 | printf '%s\n' "${tmp:-/}" 32 | } 33 | 34 | dirname ~/Pictures/Wallpapers/1.jpg 35 | #/home/black/Pictures/Wallpapers 36 | 37 | dirname ~/Pictures/Downloads/ 38 | #/home/black/Pictures 39 | 40 | basename ~/Pictures/Wallpapers/1.jpg 41 | #1.jpg 42 | 43 | basename ~/Pictures/Wallpapers/1.jpg .jpg 44 | 45 | basename ~/Pictures/Downloads/ 46 | #Downloads 47 | -------------------------------------------------------------------------------- /tests/substring.sh: -------------------------------------------------------------------------------- 1 | var="sub_string_1_2_3" 2 | echo "$var" 3 | if [[ $var == *sub_string* ]]; then 4 | printf '%s\n' "sub_string is in var." 5 | fi 6 | 7 | var="ub_string_1_2_3" 8 | # Inverse (substring not in string). 9 | if [[ $var != *sub_string* ]]; then 10 | printf '%s\n' "sub_string is not in var." 11 | fi 12 | 13 | # This works for arrays too! 14 | if [[ ${arr[*]} == *sub_string* ]]; then 15 | printf '%s\n' "sub_string is in array." 16 | fi 17 | 18 | if [[ $var == sub_string* ]]; then 19 | printf '%s\n' "var starts with sub_string." 20 | fi 21 | 22 | # Inverse (var does not start with sub_string). 23 | if [[ $var != sub_string* ]]; then 24 | printf '%s\n' "var does not start with sub_string." 25 | fi 26 | 27 | if [[ $var == *sub_string ]]; then 28 | printf '%s\n' "var ends with sub_string." 29 | fi 30 | 31 | # Inverse (var does not end with sub_string). 32 | if [[ $var != *sub_string ]]; then 33 | printf '%s\n' "var does not end with sub_string." 34 | fi 35 | -------------------------------------------------------------------------------- /tests/if7.sh: -------------------------------------------------------------------------------- 1 | decimal=15 2 | octal=017 # = 15 (decimal) 3 | hex=0x0f # = 15 (decimal) 4 | if [ "$decimal" -eq "$octal" ] 5 | then 6 | echo "$decimal equals $octal" 7 | else 8 | echo "$decimal is not equal to $octal" # 15 is not equal to 017 9 | fi # Doesn't evaluate within [ single brackets ]! 10 | if [[ "$decimal" -eq "$octal" ]] 11 | then 12 | echo "$decimal equals $octal" # 15 equals 017 13 | else 14 | echo "$decimal is not equal to $octal" 15 | fi # Evaluates within [[ double brackets ]]! 16 | if [[ "$decimal" -eq "$hex" ]] 17 | then 18 | echo "$decimal equals $hex" # 15 equals 0x0f 19 | else 20 | echo "$decimal is not equal to $hex" 21 | fi # [[ $hexadecimal ]] also evaluates! 22 | 23 | 24 | if test ! -f /fastboot 25 | then 26 | echo "file doesnot exist" 27 | fi 28 | 29 | if test -f /forcefsck 30 | then 31 | force="-f" 32 | else 33 | force="" 34 | fi 35 | 36 | echo $force 37 | 38 | if test "$FSCKFIX" = yes 39 | then 40 | fix="-y" 41 | else 42 | fix="-a" 43 | fi 44 | 45 | echo $fix 46 | -------------------------------------------------------------------------------- /tests/9.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # timeout.sh 3 | 4 | # Written by Stephane Chazelas, 5 | #+ and modified by the document author. 6 | 7 | INTERVAL=5 # timeout interval 8 | 9 | timedout_read() { 10 | timeout=$1 11 | varname=$2 12 | old_tty_settings=`stty -g` 13 | stty -icanon min 0 time ${timeout}0 14 | eval read $varname # or just read $varname 15 | stty "$old_tty_settings" 16 | # See man page for "stty." 17 | } 18 | 19 | echo; echo -n "What's your name? Quick! " 20 | timedout_read $INTERVAL your_name 21 | 22 | # This may not work on every terminal type. 23 | # The maximum timeout depends on the terminal. 24 | #+ (it is often 25.5 seconds). 25 | 26 | echo 27 | 28 | if [ ! -z "$your_name" ] # If name input before timeout ... 29 | then 30 | echo "Your name is $your_name." 31 | else 32 | echo "Timed out." 33 | fi 34 | 35 | echo 36 | 37 | # The behavior of this script differs somewhat from "timed-input.sh." 38 | # At each keystroke, the counter resets. 39 | 40 | exit 0 -------------------------------------------------------------------------------- /tests/while.sh: -------------------------------------------------------------------------------- 1 | valid=true 2 | count=1 3 | while [ $valid ] 4 | do 5 | echo $count 6 | if [ $count -eq 5 ]; 7 | then 8 | break 9 | fi 10 | ((count++)) 11 | # count=$((count + 1)) 12 | done 13 | 14 | a=0 15 | b=5 16 | 17 | while (( $a < $b )) 18 | do 19 | echo $a 20 | a=$(( a + 1 )) 21 | done 22 | 23 | 24 | i=0 25 | 26 | while [ $i -le 2 ] 27 | do 28 | echo Number: $i 29 | # ((i++)) 30 | i=$((i + 1)) 31 | done 32 | 33 | valid=true 34 | count=1 35 | while [ $valid ] 36 | do 37 | echo $count 38 | if [ $count -eq 5 ]; 39 | then 40 | break 41 | fi 42 | # ((count++)) 43 | count=$((count + 1)) 44 | done 45 | 46 | # file='book.txt' 47 | # while read line; do 48 | # echo $line 49 | # done < $file 50 | 51 | 52 | n=1 53 | while (( $n <= 5 )) 54 | do 55 | echo "Welcome $n times." 56 | n=$(( n+1 )) 57 | done 58 | 59 | 60 | n=2 61 | 62 | while [ $n -le 5 ] 63 | do 64 | echo "Welcome $n times." 65 | n=$((n+1)) 66 | 67 | done 68 | 69 | 70 | b=8 71 | while [ $b -lt 12 ] 72 | do 73 | echo "Welcome $b times." 74 | b=$((b+1)) 75 | done 76 | -------------------------------------------------------------------------------- /tests/mountall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: mountall 4 | # Required-Start: mountvirtfs 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | # Short-Description: Mount all filesystems. 9 | # Description: 10 | ### END INIT INFO 11 | 12 | . /etc/default/rcS 13 | 14 | # 15 | # Mount local filesystems in /etc/fstab. For some reason, people 16 | # might want to mount "proc" several times, and mount -v complains 17 | # about this. So we mount "proc" filesystems without -v. 18 | # 19 | test "$VERBOSE" != no && echo "Mounting local filesystems..." 20 | mount -at nonfs,nosmbfs,noncpfs 2>/dev/null 21 | 22 | # 23 | # We might have mounted something over /dev, see if /dev/initctl is there. 24 | # 25 | if test ! -p /dev/initctl 26 | then 27 | rm -f /dev/initctl 28 | mknod -m 600 /dev/initctl p 29 | fi 30 | kill -USR1 1 31 | 32 | # 33 | # Execute swapon command again, in case we want to swap to 34 | # a file on a now mounted filesystem. 35 | # 36 | [ -x /sbin/swapon ] && swapon -a 37 | 38 | : exit 0 39 | 40 | -------------------------------------------------------------------------------- /tests/3.2.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | # rpm-check.sh 4 | 5 | # Queries an rpm file for description, listing, 6 | #+ and whether it can be installed. 7 | # Saves output to a file. 8 | # 9 | # This script illustrates using a code block. 10 | 11 | SUCCESS=0 12 | E_NOARGS=65 13 | 14 | if [ -z "$1" ] 15 | then 16 | echo "Usage: `basename $0` rpm-file" 17 | exit $E_NOARGS 18 | fi 19 | 20 | { # Begin code block. 21 | echo 22 | echo "Archive Description:" 23 | rpm -qpi $1 # Query description. 24 | echo 25 | echo "Archive Listing:" 26 | rpm -qpl $1 # Query listing. 27 | echo 28 | rpm -i --test $1 # Query whether rpm file can be installed. 29 | if [ "$?" -eq $SUCCESS ] 30 | then 31 | echo "$1 can be installed." 32 | else 33 | echo "$1 cannot be installed." 34 | fi 35 | echo # End code block. 36 | } > "$1.test" # Redirects output of everything in block to file. 37 | 38 | echo "Results of rpm test in file $1.test" 39 | 40 | # See rpm man page for explanation of options. 41 | 42 | exit 0 43 | -------------------------------------------------------------------------------- /tests/6.2.sh: -------------------------------------------------------------------------------- 1 | true # The "true" builtin. 2 | echo "exit status of \"true\" = $?" # 0 3 | 4 | ! true 5 | echo "exit status of \"! true\" = $?" # 1 6 | # Note that the "!" needs a space between it and the command. 7 | # !true leads to a "command not found" error 8 | # 9 | # The '!' operator prefixing a command invokes the Bash history mechanism. 10 | 11 | true 12 | !true 13 | # No error this time, but no negation either. 14 | # It just repeats the previous command (true). 15 | 16 | 17 | # =========================================================== # 18 | # Preceding a _pipe_ with ! inverts the exit status returned. 19 | ls | bogus_command # bash: bogus_command: command not found 20 | echo $? # 127 21 | 22 | ! ls | bogus_command # bash: bogus_command: command not found 23 | echo $? # 0 24 | # Note that the ! does not change the execution of the pipe. 25 | # Only the exit status changes. 26 | # =========================================================== # 27 | 28 | # Thanks, Stéphane Chazelas and Kristopher Newsome. 29 | -------------------------------------------------------------------------------- /tests/4.5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Call this script with at least 10 parameters, for example 4 | # ./scriptname 1 2 3 4 5 6 7 8 9 10 5 | MINPARAMS=10 6 | 7 | echo 8 | 9 | echo "The name of this script is \"$0\"." 10 | # Adds ./ for current directory 11 | echo "The name of this script is \"`basename $0`\"." 12 | # Strips out path name info (see 'basename') 13 | 14 | echo 15 | 16 | if [ -n "$1" ] # Tested variable is quoted. 17 | then 18 | echo "Parameter #1 is $1" # Need quotes to escape # 19 | fi 20 | 21 | if [ -n "$2" ] 22 | then 23 | echo "Parameter #2 is $2" 24 | fi 25 | 26 | if [ -n "$3" ] 27 | then 28 | echo "Parameter #3 is $3" 29 | fi 30 | 31 | # ... 32 | 33 | 34 | if [ -n "${10}" ] # Parameters > $9 must be enclosed in {brackets}. 35 | then 36 | echo "Parameter #10 is ${10}" 37 | fi 38 | 39 | echo "-----------------------------------" 40 | echo "All the command-line parameters are: "$*"" 41 | 42 | if [ $# -lt "$MINPARAMS" ] 43 | then 44 | echo 45 | echo "This script needs at least $MINPARAMS command-line arguments!" 46 | fi 47 | 48 | echo 49 | 50 | exit 0 51 | -------------------------------------------------------------------------------- /tests/7.7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # zmore 3 | 4 | # View gzipped files with 'more' filter. 5 | 6 | E_NOARGS=85 7 | E_NOTFOUND=86 8 | E_NOTGZIP=87 9 | 10 | if [ $# -eq 0 ] # same effect as: if [ -z "$1" ] 11 | # $1 can exist, but be empty: zmore "" arg2 arg3 12 | then 13 | echo "Usage: `basename $0` filename" >&2 14 | # Error message to stderr. 15 | exit $E_NOARGS 16 | # Returns 85 as exit status of script (error code). 17 | fi 18 | 19 | filename=$1 20 | 21 | if [ ! -f "$filename" ] # Quoting $filename allows for possible spaces. 22 | then 23 | echo "File $filename not found!" >&2 # Error message to stderr. 24 | exit $E_NOTFOUND 25 | fi 26 | 27 | if [ ${filename##*.} != "gz" ] 28 | # Using bracket in variable substitution. 29 | then 30 | echo "File $1 is not a gzipped file!" 31 | exit $E_NOTGZIP 32 | fi 33 | 34 | zcat $1 | more 35 | 36 | # Uses the 'more' filter. 37 | # May substitute 'less' if desired. 38 | 39 | exit $? # Script returns exit status of pipe. 40 | # Actually "exit $?" is unnecessary, as the script will, in any case, 41 | #+ return the exit status of the last command executed. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Sinan Kaya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/stringconcat.sh: -------------------------------------------------------------------------------- 1 | var_a="Hello World" 2 | wh_domain='http://www.whitehouse.gov' 3 | wh_path='/briefing-room/press-briefings?page=' 4 | wh_base_url="$wh_domain$wh_path" 5 | 6 | echo my username is `whoami` 7 | 8 | echo "$wh_base_url" 9 | if [ "$wh_base_url" == "http://www.whitehouse.gov/briefing-room/press-briefings?page=" ]; then 10 | echo "wh_base_url matched" 11 | else 12 | echo "wh_base_url not matched" 13 | fi 14 | 15 | another_var=42 16 | echo $var_a 17 | echo "$var_a$another_var" 18 | 19 | if [ "$var_a$another_var" != "Hello World42" ]; then 20 | echo "string match" 21 | else 22 | echo "no match" 23 | fi 24 | 25 | # curl -so 10.html "$wh_base_url=10" 26 | # curl -so 20.html "$wh_base_url=20" 27 | # curl -so 30.html "$wh_base_url=30" 28 | BASE_BOT='R2' 29 | 30 | var3=$V3 31 | str="Hello, $name" 32 | 33 | echo hello 34 | echo my username is `whoami` 35 | 36 | var1=21 var2=22 var3=$V3 37 | # echo 38 | echo "var1=$var1 var2=$var2 var3=$var3" 39 | 40 | 41 | var_a="Hello World" 42 | another_var=42 43 | echo $var_a 44 | echo "$var_a$another_var" 45 | 46 | 47 | string1="Linux" 48 | string2="Hint" 49 | echo "$string1$string2" 50 | string3=$string1+$string2 51 | -------------------------------------------------------------------------------- /bash2cpp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30704.19 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "bash2cpp", "bash2cpp.njsproj", "{00FC0137-5EE7-43F1-8E56-45A0F9ED5A37}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {00FC0137-5EE7-43F1-8E56-45A0F9ED5A37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {00FC0137-5EE7-43F1-8E56-45A0F9ED5A37}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {00FC0137-5EE7-43F1-8E56-45A0F9ED5A37}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {00FC0137-5EE7-43F1-8E56-45A0F9ED5A37}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CF843539-F155-4D6C-90EC-B3298067FE44} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /tests/sysfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: mountvirtfs 4 | # Required-Start: 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | # Short-Description: Mount kernel virtual file systems. 9 | # Description: Mount initial set of virtual filesystems the kernel 10 | # provides and that are required by everything. 11 | ### END INIT INFO 12 | 13 | if [ -e /proc ] && ! [ -e /proc/mounts ]; then 14 | mount -t proc proc /proc 15 | fi 16 | 17 | if [ -e /sys ] && grep -q sysfs /proc/filesystems && ! [ -e /sys/class ]; then 18 | mount -t sysfs sysfs /sys 19 | fi 20 | 21 | if [ -e /sys/kernel/debug ] && grep -q debugfs /proc/filesystems; then 22 | mount -t debugfs debugfs /sys/kernel/debug 23 | fi 24 | 25 | if [ -e /sys/kernel/config ] && grep -q configfs /proc/filesystems; then 26 | mount -t configfs configfs /sys/kernel/config 27 | fi 28 | 29 | if [ -e /sys/firmware/efi/efivars ] && grep -q efivarfs /proc/filesystems; then 30 | mount -t efivarfs efivarfs /sys/firmware/efi/efivars 31 | fi 32 | 33 | if ! [ -e /dev/zero ] && [ -e /dev ] && grep -q devtmpfs /proc/filesystems; then 34 | mount -n -t devtmpfs devtmpfs /dev 35 | fi 36 | -------------------------------------------------------------------------------- /tests/7.2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo 4 | 5 | if test -z "$1" 6 | then 7 | echo "No command-line arguments." 8 | else 9 | echo "First command-line argument is $1." 10 | fi 11 | 12 | echo 13 | 14 | if /usr/bin/test -z "$1" # Equivalent to "test" builtin. 15 | # ^^^^^^^^^^^^^ # Specifying full pathname. 16 | then 17 | echo "No command-line arguments." 18 | else 19 | echo "First command-line argument is $1." 20 | fi 21 | 22 | echo 23 | 24 | if [ -z "$1" ] # Functionally identical to above code blocks. 25 | # if [ -z "$1" should work, but... 26 | #+ Bash responds to a missing close-bracket with an error message. 27 | then 28 | echo "No command-line arguments." 29 | else 30 | echo "First command-line argument is $1." 31 | fi 32 | 33 | echo 34 | 35 | 36 | if /usr/bin/[ -z "$1" ] # Again, functionally identical to above. 37 | # if /usr/bin/[ -z "$1" # Works, but gives an error message. 38 | # # Note: 39 | # This has been fixed in Bash, version 3.x. 40 | then 41 | echo "No command-line arguments." 42 | else 43 | echo "First command-line argument is $1." 44 | fi 45 | 46 | echo 47 | 48 | exit 0 -------------------------------------------------------------------------------- /tests/variables.sh: -------------------------------------------------------------------------------- 1 | # !/bin/bash 2 | 3 | seq 1 5 4 | echo $(seq 1 5) 5 | mkdir $(seq 1 5) 6 | n=0 7 | echo "n = $n" # n = 0 8 | 9 | ROOTFS_READ_ONLY="yes" 10 | ROOTFS_READ_ONLY=yes 11 | value="sinan" 12 | 13 | # https://linuxhint.com/30_bash_script_examples/ 14 | echo "Printing text with newline" 15 | echo -n "Printing text without newline" 16 | # echo -e "\nRemoving \t backslash \t characters\n" 17 | 18 | val=$(greeting) 19 | echo "Return value of the function is $val" 20 | 21 | 22 | # echo "Wait command" & 23 | # process_id=$! 24 | # wait $process_id 25 | # echo "Exited with status $?" 26 | 27 | # subStr=$(echo $Str| cut -d ' ' -f 1-3) 28 | # echo $subStr 29 | 30 | 31 | LOG_DIR=/var/log 32 | cd $LOG_DIR 33 | 34 | # space=`df -h | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1 -` 35 | 36 | HOSTNAME=$(/bin/hostname) 37 | 38 | 39 | SYSTEMDATE=`date -u +%4Y%2m%2d%2H%2M%2S` 40 | # format the timestamp as date expects it (2m2d2H2M4Y.2S) 41 | TS_YR=${TIMESTAMP%??????????} 42 | TS_SEC=${TIMESTAMP#????????????} 43 | TS_FIRST12=${TIMESTAMP%??} 44 | TS_MIDDLE8=${TS_FIRST12#????} 45 | date -u ${TS_MIDDLE8}${TS_YR}.${TS_SEC} 46 | test -x /etc/init.d/hwclock.sh && /etc/init.d/hwclock.sh stop 47 | -------------------------------------------------------------------------------- /tests/3.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # background-loop.sh 3 | 4 | for i in 1 2 3 4 5 6 7 8 9 10 # First loop. 5 | do 6 | echo -n "$i " 7 | done & # Run this loop in background. 8 | # Will sometimes execute after second loop. 9 | 10 | echo # This 'echo' sometimes will not display. 11 | 12 | for i in 11 12 13 14 15 16 17 18 19 20 # Second loop. 13 | do 14 | echo -n "$i " 15 | done 16 | 17 | echo # This 'echo' sometimes will not display. 18 | 19 | # ====================================================== 20 | 21 | # The expected output from the script: 22 | # 1 2 3 4 5 6 7 8 9 10 23 | # 11 12 13 14 15 16 17 18 19 20 24 | 25 | # Sometimes, though, you get: 26 | # 11 12 13 14 15 16 17 18 19 20 27 | # 1 2 3 4 5 6 7 8 9 10 bozo $ 28 | # (The second 'echo' doesn't execute. Why?) 29 | 30 | # Occasionally also: 31 | # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 32 | # (The first 'echo' doesn't execute. Why?) 33 | 34 | # Very rarely something like: 35 | # 11 12 13 1 2 3 4 5 6 7 8 9 10 14 15 16 17 18 19 20 36 | # The foreground loop preempts the background one. 37 | 38 | exit 0 39 | 40 | # Nasimuddin Ansari suggests adding sleep 1 41 | #+ after the echo -n "$i" in lines 6 and 14, 42 | #+ for some real fun. 43 | -------------------------------------------------------------------------------- /tests/5.1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # weirdvars.sh: Echoing weird variables. 3 | 4 | echo 5 | 6 | var="'(]\\{}\$\"" 7 | echo $var # '(]\{}$" 8 | echo "$var" # '(]\{}$" Doesn't make a difference. 9 | 10 | echo 11 | 12 | IFS='\' 13 | echo $var # '(] {}$" \ converted to space. Why? 14 | echo "$var" # '(]\{}$" 15 | 16 | # Examples above supplied by Stephane Chazelas. 17 | 18 | echo 19 | 20 | var2="\\\\\"" 21 | echo $var2 # " 22 | echo "$var2" # \\" 23 | echo 24 | # But ... var2="\\\\"" is illegal. Why? 25 | var3='\\\\' 26 | echo "$var3" # \\\\ 27 | # Strong quoting works, though. 28 | 29 | 30 | # ************************************************************ # 31 | # As the first example above shows, nesting quotes is permitted. 32 | 33 | echo "$(echo '"')" # " 34 | # ^ ^ 35 | 36 | 37 | # At times this comes in useful. 38 | 39 | var1="Two bits" 40 | echo "\$var1 = "$var1"" # $var1 = Two bits 41 | # ^ ^ 42 | 43 | # Or, as Chris Hiestand points out ... 44 | 45 | if [[ "$(du "$My_File1")" -gt "$(du "$My_File2")" ]] 46 | # ^ ^ ^ ^ ^ ^ ^ ^ 47 | then 48 | ... 49 | fi 50 | # ************************************************************ # 51 | -------------------------------------------------------------------------------- /tests/3.4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Backs up all files in current directory modified within last 24 hours 4 | #+ in a "tarball" (tarred and gzipped file). 5 | 6 | BACKUPFILE=backup-$(date +%m-%d-%Y) 7 | # Embeds date in backup filename. 8 | # Thanks, Joshua Tschida, for the idea. 9 | archive=${1:-$BACKUPFILE} 10 | # If no backup-archive filename specified on command-line, 11 | #+ it will default to "backup-MM-DD-YYYY.tar.gz." 12 | 13 | tar cvf - `find . -mtime -1 -type f -print` > $archive.tar 14 | gzip $archive.tar 15 | echo "Directory $PWD backed up in archive file \"$archive.tar.gz\"." 16 | 17 | 18 | # Stephane Chazelas points out that the above code will fail 19 | #+ if there are too many files found 20 | #+ or if any filenames contain blank characters. 21 | 22 | # He suggests the following alternatives: 23 | # ------------------------------------------------------------------- 24 | # find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar" 25 | # using the GNU version of "find". 26 | 27 | 28 | # find . -mtime -1 -type f -exec tar rvf "$archive.tar" '{}' \; 29 | # portable to other UNIX flavors, but much slower. 30 | # ------------------------------------------------------------------- 31 | 32 | 33 | exit 0 -------------------------------------------------------------------------------- /tests/9.6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # arglist.sh 3 | # Invoke this script with several arguments, such as "one two three" ... 4 | 5 | E_BADARGS=85 6 | 7 | if [ ! -n "$1" ] 8 | then 9 | echo "Usage: `basename $0` argument1 argument2 etc." 10 | exit $E_BADARGS 11 | fi 12 | 13 | echo 14 | 15 | index=1 # Initialize count. 16 | 17 | echo "Listing args with \"\$*\":" 18 | for arg in "$*" # Doesn't work properly if "$*" isn't quoted. 19 | do 20 | echo "Arg #$index = $arg" 21 | let "index+=1" 22 | done # $* sees all arguments as single word. 23 | echo "Entire arg list seen as single word." 24 | 25 | echo 26 | 27 | index=1 # Reset count. 28 | # What happens if you forget to do this? 29 | 30 | echo "Listing args with \"\$@\":" 31 | for arg in "$@" 32 | do 33 | echo "Arg #$index = $arg" 34 | let "index+=1" 35 | done # $@ sees arguments as separate words. 36 | echo "Arg list seen as separate words." 37 | 38 | echo 39 | 40 | index=1 # Reset count. 41 | 42 | echo "Listing args with \$* (unquoted):" 43 | for arg in $* 44 | do 45 | echo "Arg #$index = $arg" 46 | let "index+=1" 47 | done # Unquoted $* sees arguments as separate words. 48 | echo "Arg list seen as separate words." 49 | 50 | exit 0 -------------------------------------------------------------------------------- /tests/checkfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: checkfs 4 | # Required-Start: checkroot 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | # Short-Description: Check all other file systems 9 | ### END INIT INFO 10 | 11 | . /etc/default/rcS 12 | 13 | # 14 | # Check the rest of the filesystems. 15 | # 16 | if test ! -f /fastboot 17 | then 18 | if test -f /forcefsck 19 | then 20 | force="-f" 21 | else 22 | force="" 23 | fi 24 | if test "$FSCKFIX" = yes 25 | then 26 | fix="-y" 27 | else 28 | fix="-a" 29 | fi 30 | spinner="-C" 31 | case "$TERM" in 32 | dumb|network|unknown|"") spinner="" ;; 33 | esac 34 | test "`uname -m`" = "s390" && spinner="" # This should go away 35 | test "$VERBOSE" != no && echo "Checking all filesystems..." 36 | fsck $spinner -R -A $fix $force 37 | if test "$?" -gt 1 38 | then 39 | echo 40 | echo "fsck failed. Please repair manually." 41 | echo 42 | echo "CONTROL-D will exit from this shell and continue system startup." 43 | echo 44 | # Start a single user shell on the console 45 | /sbin/sulogin $CONSOLE 46 | fi 47 | fi 48 | rm -f /fastboot /forcefsck 49 | 50 | : exit 0 51 | -------------------------------------------------------------------------------- /tests/8.2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Counting to 11 in 10 different ways. 3 | 4 | n=1; echo -n "$n " 5 | 6 | let "n = $n + 1" # let "n = n + 1" also works. 7 | echo -n "$n " 8 | 9 | 10 | : $((n = $n + 1)) 11 | # ":" necessary because otherwise Bash attempts 12 | #+ to interpret "$((n = $n + 1))" as a command. 13 | echo -n "$n " 14 | 15 | (( n = n + 1 )) 16 | # A simpler alternative to the method above. 17 | # Thanks, David Lombard, for pointing this out. 18 | echo -n "$n " 19 | 20 | n=$(($n + 1)) 21 | echo -n "$n " 22 | 23 | : $[ n = $n + 1 ] 24 | # ":" necessary because otherwise Bash attempts 25 | #+ to interpret "$[ n = $n + 1 ]" as a command. 26 | # Works even if "n" was initialized as a string. 27 | echo -n "$n " 28 | 29 | n=$[ $n + 1 ] 30 | # Works even if "n" was initialized as a string. 31 | #* Avoid this type of construct, since it is obsolete and nonportable. 32 | # Thanks, Stephane Chazelas. 33 | echo -n "$n " 34 | 35 | # Now for C-style increment operators. 36 | # Thanks, Frank Wang, for pointing this out. 37 | 38 | let "n++" # let "++n" also works. 39 | echo -n "$n " 40 | 41 | (( n++ )) # (( ++n )) also works. 42 | echo -n "$n " 43 | 44 | : $(( n++ )) # : $(( ++n )) also works. 45 | echo -n "$n " 46 | 47 | : $[ n++ ] # : $[ ++n ] also works 48 | echo -n "$n " 49 | 50 | echo 51 | 52 | exit 0 -------------------------------------------------------------------------------- /tests/8.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | a=24 4 | b=47 5 | 6 | if [ "$a" -eq 24 ] && [ "$b" -eq 47 ] 7 | then 8 | echo "Test #1 succeeds." 9 | else 10 | echo "Test #1 fails." 11 | fi 12 | 13 | # ERROR: if [ "$a" -eq 24 && "$b" -eq 47 ] 14 | #+ attempts to execute ' [ "$a" -eq 24 ' 15 | #+ and fails to finding matching ']'. 16 | # 17 | # Note: if [[ $a -eq 24 && $b -eq 24 ]] works. 18 | # The double-bracket if-test is more flexible 19 | #+ than the single-bracket version. 20 | # (The "&&" has a different meaning in line 17 than in line 6.) 21 | # Thanks, Stephane Chazelas, for pointing this out. 22 | 23 | 24 | if [ "$a" -eq 98 ] || [ "$b" -eq 47 ] 25 | then 26 | echo "Test #2 succeeds." 27 | else 28 | echo "Test #2 fails." 29 | fi 30 | 31 | 32 | # The -a and -o options provide 33 | #+ an alternative compound condition test. 34 | # Thanks to Patrick Callahan for pointing this out. 35 | 36 | 37 | if [ "$a" -eq 24 -a "$b" -eq 47 ] 38 | then 39 | echo "Test #3 succeeds." 40 | else 41 | echo "Test #3 fails." 42 | fi 43 | 44 | 45 | if [ "$a" -eq 98 -o "$b" -eq 47 ] 46 | then 47 | echo "Test #4 succeeds." 48 | else 49 | echo "Test #4 fails." 50 | fi 51 | 52 | 53 | a=rhino 54 | b=crocodile 55 | if [ "$a" = rhino ] && [ "$b" = crocodile ] 56 | then 57 | echo "Test #5 succeeds." 58 | else 59 | echo "Test #5 fails." 60 | fi 61 | 62 | exit 0 -------------------------------------------------------------------------------- /tests/read-only-rootfs-hook.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /etc/default/rcS 4 | 5 | [ "$ROOTFS_READ_ONLY" = "no" ] && exit 0 6 | 7 | is_on_read_only_partition () { 8 | DIRECTORY=$1 9 | dir=`readlink -f $DIRECTORY` 10 | while true; do 11 | if [ ! -d "$dir" ]; then 12 | echo "ERROR: $dir is not a directory" 13 | exit 1 14 | else 15 | for flag in `awk -v dir=$dir '{ if ($2 == dir) { print "FOUND"; split($4,FLAGS,",") } }; \ 16 | END { for (f in FLAGS) print FLAGS[f] }' < /proc/mounts`; do 17 | [ "$flag" = "FOUND" ] && partition="read-write" 18 | [ "$flag" = "ro" ] && { partition="read-only"; break; } 19 | done 20 | if [ "$dir" = "/" -o -n "$partition" ]; then 21 | break 22 | else 23 | dir=`dirname $dir` 24 | fi 25 | fi 26 | done 27 | [ "$partition" = "read-only" ] && echo "yes" || echo "no" 28 | } 29 | 30 | if [ "$1" = "start" ] ; then 31 | if [ `is_on_read_only_partition /var/lib` = "yes" ]; then 32 | grep -q "tmpfs /var/volatile" /proc/mounts || mount /var/volatile 33 | mkdir -p /var/volatile/lib 34 | mkdir -p /var/volatile/.lib-work 35 | # Try to mount using overlay, which is much faster than copying 36 | # files. If that fails, fallback to the slower copy 37 | if ! mount -t overlay overlay -olowerdir=/var/lib,upperdir=/var/volatile/lib,workdir=/var/volatile/.lib-work /var/lib > /dev/null 2>&1; then 38 | cp -a /var/lib/* /var/volatile/lib 39 | mount --bind /var/volatile/lib /var/lib 40 | fi 41 | fi 42 | fi 43 | 44 | -------------------------------------------------------------------------------- /tests/9.2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # timed-input.sh 3 | 4 | # TMOUT=3 Also works, as of newer versions of Bash. 5 | 6 | TIMER_INTERRUPT=14 7 | TIMELIMIT=3 # Three seconds in this instance. 8 | # May be set to different value. 9 | 10 | PrintAnswer() 11 | { 12 | if [ "$answer" = TIMEOUT ] 13 | then 14 | echo $answer 15 | else # Don't want to mix up the two instances. 16 | echo "Your favorite veggie is $answer" 17 | kill $! # Kills no-longer-needed TimerOn function 18 | #+ running in background. 19 | # $! is PID of last job running in background. 20 | fi 21 | 22 | } 23 | 24 | 25 | TimerOn() 26 | { 27 | sleep $TIMELIMIT && kill -s 14 $$ & 28 | # Waits 3 seconds, then sends sigalarm to script. 29 | } 30 | 31 | 32 | Int14Vector() 33 | { 34 | answer="TIMEOUT" 35 | PrintAnswer 36 | exit $TIMER_INTERRUPT 37 | } 38 | 39 | trap Int14Vector $TIMER_INTERRUPT 40 | # Timer interrupt (14) subverted for our purposes. 41 | 42 | echo "What is your favorite vegetable " 43 | TimerOn 44 | read answer 45 | PrintAnswer 46 | 47 | 48 | # Admittedly, this is a kludgy implementation of timed input. 49 | # However, the "-t" option to "read" simplifies this task. 50 | # See the "t-out.sh" script. 51 | # However, what about timing not just single user input, 52 | #+ but an entire script? 53 | 54 | # If you need something really elegant ... 55 | #+ consider writing the application in C or C++, 56 | #+ using appropriate library functions, such as 'alarm' and 'setitimer.' 57 | 58 | exit 0 -------------------------------------------------------------------------------- /tests/case.sh: -------------------------------------------------------------------------------- 1 | case "$1" in 2 | start) 3 | start 4 | ;; 5 | 6 | stop) 7 | stop 8 | ;; 9 | 10 | status) 11 | status anacron 12 | ;; 13 | restart) 14 | stop 15 | start 16 | ;; 17 | condrestart) 18 | if test "x`pidof anacron`" != x; then 19 | stop 20 | start 21 | fi 22 | ;; 23 | 24 | *) 25 | echo "Usage: $0 {start|stop|restart|condrestart|status}" 26 | exit 1 27 | 28 | esac 29 | 30 | case "$1" in 31 | start|"") 32 | test "$VERBOSE" != no && echo "Initializing random number generator..." 33 | # Load and then save 512 bytes, which is the size of the entropy 34 | # pool. Also load the current date, in case the seed file is 35 | # empty. 36 | # ( date +%s.%N; [ -f "$RANDOM_SEED_FILE" ] && cat "$RANDOM_SEED_FILE" ) \ 37 | # >/dev/urandom 38 | rm -f "$RANDOM_SEED_FILE" 39 | umask 077 40 | # dd if=/dev/urandom of=$RANDOM_SEED_FILE count=1 \ 41 | # >/dev/null 2>&1 || echo "urandom start: failed." 42 | umask 022 43 | ;; 44 | stop) 45 | # Carry a random seed from shut-down to start-up; 46 | # see documentation in linux/drivers/char/random.c 47 | test "$VERBOSE" != no && echo "Saving random seed..." 48 | umask 077 49 | # dd if=/dev/urandom of=$RANDOM_SEED_FILE count=1 \ 50 | # >/dev/null 2>&1 || echo "urandom stop: failed." 51 | ;; 52 | *) 53 | echo "Usage: urandom {start|stop}" >&2 54 | exit 1 55 | ;; 56 | esac 57 | 58 | 59 | # echo "Enter your lucky number" 60 | # read n 61 | -------------------------------------------------------------------------------- /tests/urandom: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: urandom 4 | # Required-Start: $local_fs mountvirtfs 5 | # Required-Stop: $local_fs 6 | # Default-Start: S 7 | # Default-Stop: 0 6 8 | # Short-Description: Save and restore the random seed 9 | # Description: Save the random seed on shutdown and restore it on boot, 10 | # to ensure that the seed isn't predicable on startup 11 | # (because the boot process is predictable) 12 | ### END INIT INFO 13 | 14 | test -c /dev/urandom || exit 0 15 | 16 | RANDOM_SEED_FILE=/var/lib/urandom/random-seed 17 | 18 | . /etc/default/rcS 19 | [ -f /etc/default/urandom ] && . /etc/default/urandom 20 | 21 | case "$1" in 22 | start|"") 23 | test "$VERBOSE" != no && echo "Initializing random number generator..." 24 | # Load and then save 512 bytes, which is the size of the entropy 25 | # pool. Also load the current date, in case the seed file is 26 | # empty. 27 | ( date +%s.%N; [ -f "$RANDOM_SEED_FILE" ] && cat "$RANDOM_SEED_FILE" ) \ 28 | >/dev/urandom 29 | rm -f "$RANDOM_SEED_FILE" 30 | umask 077 31 | dd if=/dev/urandom of=$RANDOM_SEED_FILE count=1 \ 32 | >/dev/null 2>&1 || echo "urandom start: failed." 33 | umask 022 34 | ;; 35 | stop) 36 | # Carry a random seed from shut-down to start-up; 37 | # see documentation in linux/drivers/char/random.c 38 | test "$VERBOSE" != no && echo "Saving random seed..." 39 | umask 077 40 | dd if=/dev/urandom of=$RANDOM_SEED_FILE count=1 \ 41 | >/dev/null 2>&1 || echo "urandom stop: failed." 42 | ;; 43 | *) 44 | echo "Usage: urandom {start|stop}" >&2 45 | exit 1 46 | ;; 47 | esac 48 | 49 | exit 0 50 | -------------------------------------------------------------------------------- /tests/logic.sh: -------------------------------------------------------------------------------- 1 | echo "Testing \"0\"" 2 | if [ 0 ] # zero 3 | then 4 | echo "0 is true." 5 | else # Or else ... 6 | echo "0 is false." 7 | fi # 0 is true. 8 | 9 | if [ 1 ] # one 10 | then 11 | echo "1 is true." 12 | else 13 | echo "1 is false." 14 | fi # 1 is true. 15 | 16 | if [ -1 ] # minus one 17 | then 18 | echo "-1 is true." 19 | else 20 | echo "-1 is false." 21 | fi # -1 is true. 22 | 23 | if [ ] # NULL (empty condition) 24 | then 25 | echo "NULL is true." 26 | else 27 | echo "NULL is false." 28 | fi # NULL is false. 29 | 30 | if [ xyz ] # string 31 | then 32 | echo "Random string is true." 33 | else 34 | echo "Random string is false." 35 | fi # Random string is true. 36 | 37 | if [ $xyz ] # Tests if $xyz is null, but... 38 | # it's only an uninitialized variable. 39 | then 40 | echo "Uninitialized variable is true." 41 | else 42 | echo "Uninitialized variable is false." 43 | fi # Uninitialized variable is false. 44 | 45 | 46 | if [ -n "$xyz" ] # More pedantically correct. 47 | then 48 | echo "Uninitialized variable is true." 49 | else 50 | echo "Uninitialized variable is false." 51 | fi # Uninitialized variable is false. 52 | 53 | if [ "true" ] # It seems that "false" is just a string ... 54 | then 55 | echo "\"true\" is true." #+ and it tests true. 56 | else 57 | echo "\"true\" is false." 58 | fi # "false" is true. 59 | 60 | if [ "false" ] # It seems that "false" is just a string ... 61 | then 62 | echo "\"false\" is true." #+ and it tests true. 63 | else 64 | echo "\"false\" is false." 65 | fi # "false" is true. 66 | 67 | 68 | if [ "$false" ] 69 | then 70 | echo "\"\$false\" is true." 71 | else 72 | echo "\"\$false\" is false." 73 | fi # "$false" is false. 74 | # Now, we get the expected result. 75 | -------------------------------------------------------------------------------- /tests/default0.sh: -------------------------------------------------------------------------------- 1 | ######### testing + ########### 2 | # If VAR is set, use STRING as its value. 3 | echo "testing +" 4 | other=1 5 | echo ${other+default_value} 6 | echo $other 7 | echo ${othermy+default_value} 8 | echo $othermy 9 | 10 | # echo "testing ?" 11 | # echo ${other4?default_value} 12 | 13 | # echo "testing :?" 14 | # echo ${other4:?default_value} 15 | 16 | ######### testing := ########### 17 | # If VAR is empty or unset, set the value of VAR to STRING. 18 | server="s" 19 | echo ${server:=localhost} 20 | server="" 21 | echo ${server:=localhost} 22 | 23 | ######### testing :+ ########### 24 | # If VAR is not empty, use STRING as its value. 25 | default_value="def" 26 | other=1 27 | echo ${other:+default_value} 28 | echo $other 29 | other="" 30 | echo ${other:+default_value} 31 | echo $other 32 | 33 | ######### testing :- ########### 34 | # If VAR is empty or unset, use STRING as its value. 35 | echo "testing :-" 36 | other=1 37 | echo ${other:-default_value} 38 | echo $other 39 | other="" 40 | echo ${other:-default_value} 41 | echo $other 42 | 43 | ######### testing = ########### 44 | # If VAR is unset, set the value of VAR to STRING. 45 | echo ${unset=default_value} 46 | echo $unset 47 | unset=1 48 | echo ${unset=default_value} 49 | 50 | ######### testing - ########### 51 | # If VAR is unset, use STRING as its value. 52 | echo "testing -" 53 | other=1 54 | echo ${other2-default_value} 55 | echo $other2 56 | other2="1" 57 | echo ${other2-default_value} 58 | echo $other2 59 | 60 | ######### testing = ########### 61 | # If VAR is unset, set the value of VAR to STRING. 62 | echo "testing =" 63 | echo ${other3=default_value} 64 | echo $other3 65 | other3="1" 66 | echo ${other3=default_value} 67 | echo $other3 68 | 69 | ######### testing ? ########### 70 | # Display an error if unset. 71 | -------------------------------------------------------------------------------- /tests/8.5.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | # c-vars.sh 4 | # Manipulating a variable, C-style, using the (( ... )) construct. 5 | 6 | 7 | echo 8 | 9 | (( a = 23 )) # Setting a value, C-style, 10 | #+ with spaces on both sides of the "=". 11 | echo "a (initial value) = $a" # 23 12 | 13 | (( a++ )) # Post-increment 'a', C-style. 14 | echo "a (after a++) = $a" # 24 15 | 16 | (( a-- )) # Post-decrement 'a', C-style. 17 | echo "a (after a--) = $a" # 23 18 | 19 | 20 | (( ++a )) # Pre-increment 'a', C-style. 21 | echo "a (after ++a) = $a" # 24 22 | 23 | (( --a )) # Pre-decrement 'a', C-style. 24 | echo "a (after --a) = $a" # 23 25 | 26 | echo 27 | 28 | ######################################################## 29 | # Note that, as in C, pre- and post-decrement operators 30 | #+ have different side-effects. 31 | 32 | n=1; let --n && echo "True" || echo "False" # False 33 | n=1; let n-- && echo "True" || echo "False" # True 34 | 35 | # Thanks, Jeroen Domburg. 36 | ######################################################## 37 | 38 | echo 39 | 40 | (( t = a<45?7:11 )) # C-style trinary operator. 41 | # ^ ^ ^ 42 | echo "If a < 45, then t = 7, else t = 11." # a = 23 43 | echo "t = $t " # t = 7 44 | 45 | echo 46 | 47 | 48 | # ----------------- 49 | # Easter Egg alert! 50 | # ----------------- 51 | # Chet Ramey seems to have snuck a bunch of undocumented C-style 52 | #+ constructs into Bash (actually adapted from ksh, pretty much). 53 | # In the Bash docs, Ramey calls (( ... )) shell arithmetic, 54 | #+ but it goes far beyond that. 55 | # Sorry, Chet, the secret is out. 56 | 57 | # See also "for" and "while" loops using the (( ... )) construct. 58 | 59 | # These work only with version 2.04 or later of Bash. 60 | 61 | exit -------------------------------------------------------------------------------- /tests/7.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # arith-tests.sh 3 | # Arithmetic tests. 4 | 5 | # The (( ... )) construct evaluates and tests numerical expressions. 6 | # Exit status opposite from [ ... ] construct! 7 | 8 | (( 0 )) 9 | echo "Exit status of \"(( 0 ))\" is $?." # 1 10 | 11 | (( 1 )) 12 | echo "Exit status of \"(( 1 ))\" is $?." # 0 13 | 14 | (( 5 > 4 )) # true 15 | echo "Exit status of \"(( 5 > 4 ))\" is $?." # 0 16 | 17 | (( 5 > 9 )) # false 18 | echo "Exit status of \"(( 5 > 9 ))\" is $?." # 1 19 | 20 | (( 5 == 5 )) # true 21 | echo "Exit status of \"(( 5 == 5 ))\" is $?." # 0 22 | # (( 5 = 5 )) gives an error message. 23 | 24 | (( 5 - 5 )) # 0 25 | echo "Exit status of \"(( 5 - 5 ))\" is $?." # 1 26 | 27 | (( 5 / 4 )) # Division o.k. 28 | echo "Exit status of \"(( 5 / 4 ))\" is $?." # 0 29 | 30 | (( 1 / 2 )) # Division result < 1. 31 | echo "Exit status of \"(( 1 / 2 ))\" is $?." # Rounded off to 0. 32 | # 1 33 | 34 | (( 1 / 0 )) 2>/dev/null # Illegal division by 0. 35 | # ^^^^^^^^^^^ 36 | echo "Exit status of \"(( 1 / 0 ))\" is $?." # 1 37 | 38 | # What effect does the "2>/dev/null" have? 39 | # What would happen if it were removed? 40 | # Try removing it, then rerunning the script. 41 | 42 | # ======================================= # 43 | 44 | # (( ... )) also useful in an if-then test. 45 | 46 | var1=5 47 | var2=4 48 | 49 | if (( var1 > var2 )) 50 | then #^ ^ Note: Not $var1, $var2. Why? 51 | echo "$var1 is greater than $var2" 52 | fi # 5 is greater than 4 53 | 54 | exit 0 -------------------------------------------------------------------------------- /tests/wordexp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | int tokenize(std::string str) 26 | { 27 | std::vector tokens; 28 | std::string delimiter = ""; 29 | int ret = 0; 30 | size_t pos = 0; 31 | size_t prev = 0; 32 | if (str.front() == '\'') prev++; 33 | 34 | while ((pos = str.find_first_of(delimiter, prev)) != std::string::npos) { 35 | if (pos > prev) 36 | tokens.push_back(str.substr(prev, pos-prev)); 37 | prev = pos+1; 38 | } 39 | if (prev < str.length()){ 40 | size_t end = str.length() - prev; 41 | if (str.back() == '\'') end--; 42 | tokens.push_back(str.substr(prev, end)); 43 | } 44 | 45 | return ret; 46 | } 47 | 48 | int execWrapper(std::string str) 49 | { 50 | std::vector toks; 51 | wordexp_t p; 52 | char **w; 53 | int ret; 54 | 55 | ret = wordexp(str.c_str(), &p, 0 ); 56 | if (ret) { 57 | tokenize(str); 58 | return ret; 59 | } 60 | w = p.we_wordv; 61 | for (int i = 0; i < p.we_wordc; i++) { 62 | toks.push_back(w[i]); 63 | } 64 | toks.push_back(NULL); 65 | 66 | for (auto &a: toks) { 67 | std::cout << a << std::endl; 68 | } 69 | wordfree(&p); 70 | 71 | return ret; 72 | } 73 | 74 | int main(void) 75 | { 76 | // execWrapper(std::string("ls -la")); 77 | execWrapper(std::string("ls ' hye -la' rr \"3e3e\" 1&>2")); 78 | return 0; 79 | } -------------------------------------------------------------------------------- /tests/8.4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # numbers.sh: Representation of numbers in different bases. 3 | 4 | # Decimal: the default 5 | let "dec = 32" 6 | echo "decimal number = $dec" # 32 7 | # Nothing out of the ordinary here. 8 | 9 | 10 | # Octal: numbers preceded by '0' (zero) 11 | let "oct = 032" 12 | echo "octal number = $oct" # 26 13 | # Expresses result in decimal. 14 | # --------- ------ -- ------- 15 | 16 | 17 | # Hexadecimal: numbers preceded by '0x' or '0X' 18 | let "hex = 0x32" 19 | echo "hexadecimal number = $hex" # 50 20 | 21 | echo $((0x9abc)) # 39612 22 | # ^^ ^^ double-parentheses arithmetic expansion/evaluation 23 | # Expresses result in decimal. 24 | 25 | 26 | 27 | # Other bases: BASE#NUMBER 28 | # BASE between 2 and 64. 29 | # NUMBER must use symbols within the BASE range, see below. 30 | 31 | 32 | let "bin = 2#111100111001101" 33 | echo "binary number = $bin" # 31181 34 | 35 | let "b32 = 32#77" 36 | echo "base-32 number = $b32" # 231 37 | 38 | let "b64 = 64#@_" 39 | echo "base-64 number = $b64" # 4031 40 | # This notation only works for a limited range (2 - 64) of ASCII characters. 41 | # 10 digits + 26 lowercase characters + 26 uppercase characters + @ + _ 42 | 43 | 44 | echo 45 | 46 | echo $((36#zz)) $((2#10101010)) $((16#AF16)) $((53#1aA)) 47 | # 1295 170 44822 3375 48 | 49 | 50 | # Important note: 51 | # -------------- 52 | # Using a digit out of range of the specified base notation 53 | #+ gives an error message. 54 | 55 | let "bad_oct = 081" 56 | # (Partial) error message output: 57 | # bad_oct = 081: value too great for base (error token is "081") 58 | # Octal numbers use only digits in the range 0 - 7. 59 | 60 | exit $? # Exit value = 1 (error) 61 | 62 | # Thanks, Rich Bartell and Stephane Chazelas, for clarification. -------------------------------------------------------------------------------- /tests/9.1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ifs.sh 3 | 4 | 5 | var1="a+b+c" 6 | var2="d-e-f" 7 | var3="g,h,i" 8 | 9 | IFS=+ 10 | # The plus sign will be interpreted as a separator. 11 | echo $var1 # a b c 12 | echo $var2 # d-e-f 13 | echo $var3 # g,h,i 14 | 15 | echo 16 | 17 | IFS="-" 18 | # The plus sign reverts to default interpretation. 19 | # The minus sign will be interpreted as a separator. 20 | echo $var1 # a+b+c 21 | echo $var2 # d e f 22 | echo $var3 # g,h,i 23 | 24 | echo 25 | 26 | IFS="," 27 | # The comma will be interpreted as a separator. 28 | # The minus sign reverts to default interpretation. 29 | echo $var1 # a+b+c 30 | echo $var2 # d-e-f 31 | echo $var3 # g h i 32 | 33 | echo 34 | 35 | IFS=" " 36 | # The space character will be interpreted as a separator. 37 | # The comma reverts to default interpretation. 38 | echo $var1 # a+b+c 39 | echo $var2 # d-e-f 40 | echo $var3 # g,h,i 41 | 42 | # ======================================================== # 43 | 44 | # However ... 45 | # $IFS treats whitespace differently than other characters. 46 | 47 | output_args_one_per_line() 48 | { 49 | for arg 50 | do 51 | echo "[$arg]" 52 | done # ^ ^ Embed within brackets, for your viewing pleasure. 53 | } 54 | 55 | echo; echo "IFS=\" \"" 56 | echo "-------" 57 | 58 | IFS=" " 59 | var=" a b c " 60 | # ^ ^^ ^^^ 61 | output_args_one_per_line $var # output_args_one_per_line `echo " a b c "` 62 | # [a] 63 | # [b] 64 | # [c] 65 | 66 | 67 | echo; echo "IFS=:" 68 | echo "-----" 69 | 70 | IFS=: 71 | var=":a::b:c:::" # Same pattern as above, 72 | # ^ ^^ ^^^ #+ but substituting ":" for " " ... 73 | output_args_one_per_line $var 74 | # [] 75 | # [a] 76 | # [] 77 | # [b] 78 | # [c] 79 | # [] 80 | # [] 81 | 82 | # Note "empty" brackets. 83 | # The same thing happens with the "FS" field separator in awk. 84 | 85 | 86 | echo 87 | 88 | exit -------------------------------------------------------------------------------- /tests/7.4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # broken-link.sh 3 | # Written by Lee bigelow 4 | # Used in ABS Guide with permission. 5 | 6 | # A pure shell script to find dead symlinks and output them quoted 7 | #+ so they can be fed to xargs and dealt with :) 8 | #+ eg. sh broken-link.sh /somedir /someotherdir|xargs rm 9 | # 10 | # This, however, is a better method: 11 | # 12 | # find "somedir" -type l -print0|\ 13 | # xargs -r0 file|\ 14 | # grep "broken symbolic"| 15 | # sed -e 's/^\|: *broken symbolic.*$/"/g' 16 | # 17 | #+ but that wouldn't be pure Bash, now would it. 18 | # Caution: beware the /proc file system and any circular links! 19 | ################################################################ 20 | 21 | 22 | # If no args are passed to the script set directories-to-search 23 | #+ to current directory. Otherwise set the directories-to-search 24 | #+ to the args passed. 25 | ###################### 26 | 27 | [ $# -eq 0 ] && directorys=`pwd` || directorys=$@ 28 | 29 | 30 | # Setup the function linkchk to check the directory it is passed 31 | #+ for files that are links and don't exist, then print them quoted. 32 | # If one of the elements in the directory is a subdirectory then 33 | #+ send that subdirectory to the linkcheck function. 34 | ########## 35 | 36 | linkchk () { 37 | for element in $1/*; do 38 | [ -h "$element" -a ! -e "$element" ] && echo \"$element\" 39 | [ -d "$element" ] && linkchk $element 40 | # Of course, '-h' tests for symbolic link, '-d' for directory. 41 | done 42 | } 43 | 44 | # Send each arg that was passed to the script to the linkchk() function 45 | #+ if it is a valid directoy. If not, then print the error message 46 | #+ and usage info. 47 | ################## 48 | for directory in $directorys; do 49 | if [ -d $directory ] 50 | then linkchk $directory 51 | else 52 | echo "$directory is not a directory" 53 | echo "Usage: $0 dir1 dir2 ..." 54 | fi 55 | done 56 | 57 | exit $? -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | pull_request: 10 | branches: [ main ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 20 | node-version: [12.x] 21 | steps: 22 | - uses: actions/checkout@v2 23 | with: 24 | submodules: true 25 | - name: Use Node.js ${{ matrix.node-version }} 26 | uses: actions/setup-node@v1 27 | with: 28 | node-version: ${{ matrix.node-version }} 29 | - name: Setup dependencies 30 | run: | 31 | sudo apt-get update --fix-missing 32 | sudo apt-get install -y build-essential 33 | sudo apt-get install -y python3 34 | sudo apt-get install -y libboost-all-dev 35 | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 36 | sudo apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-6.0 main" 37 | sudo apt-get update 38 | sudo apt-get install -y clang 39 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test 40 | sudo apt install gcc-9 g++-9 41 | sudo update-alternatives \ 42 | --install /usr/bin/gcc gcc /usr/bin/gcc-9 100 \ 43 | --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-9 \ 44 | --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-9 \ 45 | --slave /usr/bin/gcov gcov /usr/bin/gcov-9 46 | sudo update-alternatives \ 47 | --install /usr/bin/g++ g++ /usr/bin/g++-9 100 48 | - run: npm ci 49 | - run: npm run build --if-present 50 | - run: npm test 51 | -------------------------------------------------------------------------------- /tests/8.1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # gcd.sh: greatest common divisor 3 | # Uses Euclid's algorithm 4 | 5 | # The "greatest common divisor" (gcd) of two integers 6 | #+ is the largest integer that will divide both, leaving no remainder. 7 | 8 | # Euclid's algorithm uses successive division. 9 | # In each pass, 10 | #+ dividend <--- divisor 11 | #+ divisor <--- remainder 12 | #+ until remainder = 0. 13 | # The gcd = dividend, on the final pass. 14 | # 15 | # For an excellent discussion of Euclid's algorithm, see 16 | #+ Jim Loy's site, http://www.jimloy.com/number/euclids.htm. 17 | 18 | 19 | # ------------------------------------------------------ 20 | # Argument check 21 | ARGS=2 22 | E_BADARGS=85 23 | 24 | if [ $# -ne "$ARGS" ] 25 | then 26 | echo "Usage: `basename $0` first-number second-number" 27 | exit $E_BADARGS 28 | fi 29 | # ------------------------------------------------------ 30 | 31 | 32 | gcd () 33 | { 34 | 35 | dividend=$1 # Arbitrary assignment. 36 | divisor=$2 #! It doesn't matter which of the two is larger. 37 | # Why not? 38 | 39 | remainder=1 # If an uninitialized variable is used inside 40 | #+ test brackets, an error message results. 41 | 42 | until [ "$remainder" -eq 0 ] 43 | do # ^^^^^^^^^^ Must be previously initialized! 44 | let "remainder = $dividend % $divisor" 45 | dividend=$divisor # Now repeat with 2 smallest numbers. 46 | divisor=$remainder 47 | done # Euclid's algorithm 48 | 49 | } # Last $dividend is the gcd. 50 | 51 | 52 | gcd $1 $2 53 | 54 | echo; echo "GCD of $1 and $2 = $dividend"; echo 55 | 56 | 57 | # Exercises : 58 | # --------- 59 | # 1) Check command-line arguments to make sure they are integers, 60 | #+ and exit the script with an appropriate error message if not. 61 | # 2) Rewrite the gcd () function to use local variables. 62 | 63 | exit 0 -------------------------------------------------------------------------------- /tests/mountnfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: mountnfs 4 | # Required-Start: $local_fs $network $rpcbind 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | ### END INIT INFO 9 | 10 | # 11 | # Run in a subshell because of I/O redirection. 12 | # 13 | test -f /etc/fstab && ( 14 | 15 | # 16 | # Read through fstab line by line. If it is NFS, set the flag 17 | # for mounting NFS filesystems. If any NFS partition is found and it 18 | # not mounted with the nolock option, we start the rpcbind. 19 | # 20 | rpcbind=no 21 | mount_nfs=no 22 | mount_smb=no 23 | mount_ncp=no 24 | mount_cifs=no 25 | while read device mountpt fstype options 26 | do 27 | case "$device" in 28 | ""|\#*) 29 | continue 30 | ;; 31 | esac 32 | 33 | case "$options" in 34 | *noauto*) 35 | continue 36 | ;; 37 | esac 38 | 39 | if test "$fstype" = nfs 40 | then 41 | mount_nfs=yes 42 | case "$options" in 43 | *nolock*) 44 | ;; 45 | *) 46 | rpcbind=yes 47 | ;; 48 | esac 49 | fi 50 | if test "$fstype" = smbfs 51 | then 52 | mount_smb=yes 53 | fi 54 | if test "$fstype" = ncpfs 55 | then 56 | mount_ncp=yes 57 | fi 58 | if test "$fstype" = cifs 59 | then 60 | mount_cifs=yes 61 | fi 62 | done 63 | 64 | exec 0>&1 65 | 66 | if test "$rpcbind" = yes 67 | then 68 | if test -x /usr/sbin/rpcbind 69 | then 70 | service rpcbind status > /dev/null 71 | if [ $? != 0 ]; then 72 | echo -n "Starting rpcbind..." 73 | start-stop-daemon --start --quiet --exec /usr/sbin/rpcbind 74 | sleep 2 75 | fi 76 | fi 77 | fi 78 | 79 | if test "$mount_nfs" = yes || test "$mount_smb" = yes || test "$mount_ncp" = yes || test "$mount_cifs" = yes 80 | then 81 | echo "Mounting remote filesystems..." 82 | test "$mount_nfs" = yes && mount -a -t nfs 83 | test "$mount_smb" = yes && mount -a -t smbfs 84 | test "$mount_ncp" = yes && mount -a -t ncpfs 85 | test "$mount_cifs" = yes && mount -a -t cifs 86 | fi 87 | 88 | ) < /etc/fstab 89 | 90 | : exit 0 91 | 92 | -------------------------------------------------------------------------------- /tests/var1.sh: -------------------------------------------------------------------------------- 1 | NUMBER_TWO=$(( 1 + 1 )) # addition 2 | 3 | echo The Number Two: $NUMBER_TWO 4 | NUMBER_SIX=$(( $NUMBER_TWO * 3 )) # multiplication 5 | NUMBER_THREE=$(( $NUMBER_SIX / 2 )) # division 6 | NUMBER_FOUR=$(( $NUMBER_SIX - $NUMBER_TWO )) # subtraction 7 | NUMBER_ONE=$(( $NUMBER_FOUR % $NUMBER_THREE )) # modulo 8 | 9 | echo The Number Six: $NUMBER_SIX 10 | echo The Number Three: $NUMBER_THREE 11 | echo The Number Four: $NUMBER_FOUR 12 | echo The Number One: $NUMBER_ONE 13 | 14 | # Initialize variables. Variable assigments cannot have spaces between '='. 15 | greeting="Welcome" 16 | user=$(whoami) 17 | day=$(date +%A) 18 | 19 | # Echo strings using variables. 20 | echo "$greeting $user! Today is $day." 21 | 22 | a="Hello" 23 | b="world" 24 | 25 | # echo $a", "$b"!" 26 | echo "$a, $b!" 27 | echo "${a}, ${b}!" 28 | 29 | str=$a 30 | # str+=", " 31 | # str+=$b 32 | # str+="!" 33 | echo $str 34 | 35 | 36 | # the output can also be assigned to another variable. 37 | BASH_BIN=$( which bash ) 38 | 39 | # the which command returns the whole path for the given executable. 40 | echo the bash binary is located at $BASH_BIN 41 | # echo the bash binary is located at $( which bash ) # same output as above. 42 | 43 | # you can even embed a command inside of another command. 44 | # echo the bash binary is located at $( dirname $( which bash ) ) 45 | 46 | # VAR_ONE="value\n" # 47 | # VAR_TWO='value\n' 48 | # VAR_THREE=value\\n 49 | 50 | # command output can be piped to an inline string, 51 | # just like a declared variable using $( ... ) 52 | 53 | # this line will inject the output of the printf command into the string. 54 | # echo This is VAR_ONE: $( printf $VAR_ONE ), VAR_TWO: $( printf $VAR_TWO ), VAR_THREE: $( printf $VAR_THREE ) 55 | 56 | 57 | Year=`date +%Y` 58 | Month=`date +%m` 59 | Day=`date +%d` 60 | Hour=`date +%H` 61 | Minute=`date +%M` 62 | Second=`date +%S` 63 | echo `date` 64 | # echo "Current Date is: $Day-$Month-$Year" 65 | # echo "Current Time is: $Hour:$Minute:$Second" 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bash2cpp", 3 | "version": "1.0.0", 4 | "description": "Converts bash script to C++ code. Useful for simple shell scripts that can be converted to C++ for speed", 5 | "main": "app.js", 6 | "author": "Sinan Kaya", 7 | "license": "MIT", 8 | "bugs": { 9 | "url": "https://github.com/franksinankaya/bash2cpp/issues" 10 | }, 11 | "keywords": [ 12 | "linux", 13 | "bash", 14 | "converter", 15 | "cpp", 16 | "codegenerator" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/franksinankaya/bash2cpp.git" 21 | }, 22 | "homepage": "https://github.com/franksinankaya/bash2cpp#readme", 23 | "scripts": { 24 | "prebuild": "mgb bash-parser/src/modes posix && mgb bash-parser/src/modes bash && mgb bash-parser/src/modes word-expansion", 25 | "build": "tsc --build", 26 | "clean": "tsc --build --clean", 27 | "test": "python3 test.py" 28 | }, 29 | "devDependencies": { 30 | "@types/node": "^15.3.0", 31 | "ava": "^5.1.0", 32 | "coveralls": "^3.1.0", 33 | "json5": "^2.2.3", 34 | "mode-grammar-builder": "^0.6.0", 35 | "nyc": "^15.1.0", 36 | "xo": "^0.56.0" 37 | }, 38 | "dependencies": { 39 | "array-last": "^1.1.1", 40 | "babylon": "^6.9.1", 41 | "compose-function": "^3.0.3", 42 | "curry": "^1.2.0", 43 | "deep-freeze": "0.0.1", 44 | "filter-iterator": "0.0.1", 45 | "filter-obj": "^2.0.2", 46 | "has-own-property": "^1.0.0", 47 | "identity-function": "^1.0.0", 48 | "iterable-lookahead": "^2.0.0", 49 | "iterable-transform-replace": "^1.1.1", 50 | "magic-string": "^0.25.7", 51 | "map-iterable": "^1.0.1", 52 | "map-obj": "^4.2.1", 53 | "object-pairs": "^0.1.0", 54 | "object-values": "^2.0.0", 55 | "reverse-arguments": "^1.0.0", 56 | "shell-quote-word": "^1.0.1", 57 | "to-pascal-case": "^1.0.0", 58 | "transform-spread-iterable": "^1.1.0", 59 | "trim": "^1.0.1", 60 | "typescript": "^4.6.3", 61 | "underscore": "^1.13.1", 62 | "unescape-js": "^1.0.5", 63 | "webpack": "^5.80.0" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/7.6.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | # str-test.sh: Testing null strings and unquoted strings, 4 | #+ but not strings and sealing wax, not to mention cabbages and kings . . . 5 | 6 | # Using if [ ... ] 7 | 8 | # If a string has not been initialized, it has no defined value. 9 | # This state is called "null" (not the same as zero!). 10 | 11 | if [ -n $string1 ] # string1 has not been declared or initialized. 12 | then 13 | echo "String \"string1\" is not null." 14 | else 15 | echo "String \"string1\" is null." 16 | fi # Wrong result. 17 | # Shows $string1 as not null, although it was not initialized. 18 | 19 | echo 20 | 21 | # Let's try it again. 22 | 23 | if [ -n "$string1" ] # This time, $string1 is quoted. 24 | then 25 | echo "String \"string1\" is not null." 26 | else 27 | echo "String \"string1\" is null." 28 | fi # Quote strings within test brackets! 29 | 30 | echo 31 | 32 | if [ $string1 ] # This time, $string1 stands naked. 33 | then 34 | echo "String \"string1\" is not null." 35 | else 36 | echo "String \"string1\" is null." 37 | fi # This works fine. 38 | # The [ ... ] test operator alone detects whether the string is null. 39 | # However it is good practice to quote it (if [ "$string1" ]). 40 | # 41 | # As Stephane Chazelas points out, 42 | # if [ $string1 ] has one argument, "]" 43 | # if [ "$string1" ] has two arguments, the empty "$string1" and "]" 44 | 45 | 46 | echo 47 | 48 | 49 | string1=initialized 50 | 51 | if [ $string1 ] # Again, $string1 stands unquoted. 52 | then 53 | echo "String \"string1\" is not null." 54 | else 55 | echo "String \"string1\" is null." 56 | fi # Again, gives correct result. 57 | # Still, it is better to quote it ("$string1"), because . . . 58 | 59 | 60 | string1="a = b" 61 | 62 | if [ $string1 ] # Again, $string1 stands unquoted. 63 | then 64 | echo "String \"string1\" is not null." 65 | else 66 | echo "String \"string1\" is null." 67 | fi # Not quoting "$string1" now gives wrong result! 68 | 69 | exit 0 # Thank you, also, Florian Wisser, for the "heads-up". -------------------------------------------------------------------------------- /tests/4.4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # int-or-string.sh 3 | 4 | a=2334 # Integer. 5 | let "a += 1" 6 | echo "a = $a " # a = 2335 7 | echo # Integer, still. 8 | 9 | 10 | b=${a/23/BB} # Substitute "BB" for "23". 11 | # This transforms $b into a string. 12 | echo "b = $b" # b = BB35 13 | declare -i b # Declaring it an integer doesn't help. 14 | echo "b = $b" # b = BB35 15 | 16 | let "b += 1" # BB35 + 1 17 | echo "b = $b" # b = 1 18 | echo # Bash sets the "integer value" of a string to 0. 19 | 20 | c=BB34 21 | echo "c = $c" # c = BB34 22 | d=${c/BB/23} # Substitute "23" for "BB". 23 | # This makes $d an integer. 24 | echo "d = $d" # d = 2334 25 | let "d += 1" # 2334 + 1 26 | echo "d = $d" # d = 2335 27 | echo 28 | 29 | 30 | # What about null variables? 31 | e='' # ... Or e="" ... Or e= 32 | echo "e = $e" # e = 33 | let "e += 1" # Arithmetic operations allowed on a null variable? 34 | echo "e = $e" # e = 1 35 | echo # Null variable transformed into an integer. 36 | 37 | # What about undeclared variables? 38 | echo "f = $f" # f = 39 | let "f += 1" # Arithmetic operations allowed? 40 | echo "f = $f" # f = 1 41 | echo # Undeclared variable transformed into an integer. 42 | # 43 | # However ... 44 | let "f /= $undecl_var" # Divide by zero? 45 | # let: f /= : syntax error: operand expected (error token is " ") 46 | # Syntax error! Variable $undecl_var is not set to zero here! 47 | # 48 | # But still ... 49 | let "f /= 0" 50 | # let: f /= 0: division by 0 (error token is "0") 51 | # Expected behavior. 52 | 53 | 54 | # Bash (usually) sets the "integer value" of null to zero 55 | #+ when performing an arithmetic operation. 56 | # But, don't try this at home, folks! 57 | # It's undocumented and probably non-portable behavior. 58 | 59 | 60 | # Conclusion: Variables in Bash are untyped, 61 | #+ with all attendant consequences. 62 | 63 | exit $? 64 | -------------------------------------------------------------------------------- /tests/bootmisc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: bootmisc 4 | # Required-Start: $local_fs mountvirtfs 5 | # Required-Stop: $local_fs 6 | # Default-Start: S 7 | # Default-Stop: 0 6 8 | # Short-Description: Misc and other. 9 | ### END INIT INFO 10 | 11 | TIMESTAMP_FILE=/etc/timestamp 12 | 13 | . /etc/default/rcS 14 | [ -f /etc/default/timestamp ] && . /etc/default/timestamp 15 | # 16 | # Put a nologin file in /etc to prevent people from logging in before 17 | # system startup is complete. 18 | # 19 | if test "$DELAYLOGIN" = yes 20 | then 21 | echo "System bootup in progress - please wait" > /etc/nologin 22 | cp /etc/nologin /etc/nologin.boot 23 | fi 24 | 25 | # 26 | # Set pseudo-terminal access permissions. 27 | # 28 | if test -c /dev/ttyp0 29 | then 30 | chmod 666 /dev/tty[p-za-e][0-9a-f] 31 | chown root:tty /dev/tty[p-za-e][0-9a-f] 32 | fi 33 | 34 | # 35 | # Apply /proc settings if defined 36 | # 37 | SYSCTL_CONF="/etc/sysctl.conf" 38 | if [ -f "${SYSCTL_CONF}" ] 39 | then 40 | if [ -x "/sbin/sysctl" ] 41 | then 42 | # busybox sysctl does not support -q 43 | VERBOSE_REDIR="1>/dev/null" 44 | if [ "${VERBOSE}" != "no" ]; then 45 | VERBOSE_REDIR="1>&1" 46 | fi 47 | eval /sbin/sysctl -p "${SYSCTL_CONF}" $VERBOSE_REDIR 48 | else 49 | echo "To have ${SYSCTL_CONF} applied during boot, install package ." 50 | fi 51 | fi 52 | 53 | # 54 | # Update /etc/motd. 55 | # 56 | if test "$EDITMOTD" != no 57 | then 58 | uname -a > /etc/motd.tmp 59 | sed 1d /etc/motd >> /etc/motd.tmp 60 | mv /etc/motd.tmp /etc/motd 61 | fi 62 | 63 | # 64 | # This is as good a place as any for a sanity check 65 | # 66 | # Set the system clock from hardware clock 67 | # If the timestamp is more recent than the current time, 68 | # use the timestamp instead. 69 | test -x /etc/init.d/hwclock.sh && /etc/init.d/hwclock.sh start 70 | if test -e "$TIMESTAMP_FILE" 71 | then 72 | SYSTEMDATE=`date -u +%4Y%2m%2d%2H%2M%2S` 73 | read TIMESTAMP < "$TIMESTAMP_FILE" 74 | if [ ${TIMESTAMP} -gt $SYSTEMDATE ]; then 75 | # format the timestamp as date expects it (2m2d2H2M4Y.2S) 76 | TS_YR=${TIMESTAMP%??????????} 77 | TS_SEC=${TIMESTAMP#????????????} 78 | TS_FIRST12=${TIMESTAMP%??} 79 | TS_MIDDLE8=${TS_FIRST12#????} 80 | date -u ${TS_MIDDLE8}${TS_YR}.${TS_SEC} 81 | test -x /etc/init.d/hwclock.sh && /etc/init.d/hwclock.sh stop 82 | fi 83 | fi 84 | : exit 0 85 | -------------------------------------------------------------------------------- /tests/5.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Author: Sigurd Solaas, 20 Apr 2011 3 | # Used in ABS Guide with permission. 4 | # Requires version 4.2+ of Bash. 5 | 6 | key="no value yet" 7 | while true; do 8 | clear 9 | echo "Bash Extra Keys Demo. Keys to try:" 10 | echo 11 | echo "* Insert, Delete, Home, End, Page_Up and Page_Down" 12 | echo "* The four arrow keys" 13 | echo "* Tab, enter, escape, and space key" 14 | echo "* The letter and number keys, etc." 15 | echo 16 | echo " d = show date/time" 17 | echo " q = quit" 18 | echo "================================" 19 | echo 20 | 21 | # Convert the separate home-key to home-key_num_7: 22 | if [ "$key" = $'\x1b\x4f\x48' ]; then 23 | key=$'\x1b\x5b\x31\x7e' 24 | # Quoted string-expansion construct. 25 | fi 26 | 27 | # Convert the separate end-key to end-key_num_1. 28 | if [ "$key" = $'\x1b\x4f\x46' ]; then 29 | key=$'\x1b\x5b\x34\x7e' 30 | fi 31 | 32 | case "$key" in 33 | $'\x1b\x5b\x32\x7e') # Insert 34 | echo Insert Key 35 | ;; 36 | $'\x1b\x5b\x33\x7e') # Delete 37 | echo Delete Key 38 | ;; 39 | $'\x1b\x5b\x31\x7e') # Home_key_num_7 40 | echo Home Key 41 | ;; 42 | $'\x1b\x5b\x34\x7e') # End_key_num_1 43 | echo End Key 44 | ;; 45 | $'\x1b\x5b\x35\x7e') # Page_Up 46 | echo Page_Up 47 | ;; 48 | $'\x1b\x5b\x36\x7e') # Page_Down 49 | echo Page_Down 50 | ;; 51 | $'\x1b\x5b\x41') # Up_arrow 52 | echo Up arrow 53 | ;; 54 | $'\x1b\x5b\x42') # Down_arrow 55 | echo Down arrow 56 | ;; 57 | $'\x1b\x5b\x43') # Right_arrow 58 | echo Right arrow 59 | ;; 60 | $'\x1b\x5b\x44') # Left_arrow 61 | echo Left arrow 62 | ;; 63 | $'\x09') # Tab 64 | echo Tab Key 65 | ;; 66 | $'\x0a') # Enter 67 | echo Enter Key 68 | ;; 69 | $'\x1b') # Escape 70 | echo Escape Key 71 | ;; 72 | $'\x20') # Space 73 | echo Space Key 74 | ;; 75 | d) 76 | date 77 | ;; 78 | q) 79 | echo Time to quit... 80 | echo 81 | exit 0 82 | ;; 83 | *) 84 | echo You pressed: \'"$key"\' 85 | ;; 86 | esac 87 | 88 | echo 89 | echo "================================" 90 | 91 | unset K1 K2 K3 92 | read -s -N1 -p "Press a key: " 93 | K1="$REPLY" 94 | read -s -N2 -t 0.001 95 | K2="$REPLY" 96 | read -s -N1 -t 0.001 97 | K3="$REPLY" 98 | key="$K1$K2$K3" 99 | 100 | done 101 | 102 | exit $? -------------------------------------------------------------------------------- /tests/2.3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Cleanup, version 3 3 | 4 | # Warning: 5 | # ------- 6 | # This script uses quite a number of features that will be explained 7 | #+ later on. 8 | # By the time you've finished the first half of the book, 9 | #+ there should be nothing mysterious about it. 10 | 11 | 12 | 13 | LOG_DIR=/var/log 14 | ROOT_UID=0 # Only users with $UID 0 have root privileges. 15 | LINES=50 # Default number of lines saved. 16 | E_XCD=86 # Can't change directory? 17 | E_NOTROOT=87 # Non-root exit error. 18 | 19 | 20 | # Run as root, of course. 21 | if [ "$UID" -ne "$ROOT_UID" ] 22 | then 23 | echo "Must be root to run this script." 24 | exit $E_NOTROOT 25 | fi 26 | 27 | if [ -n "$1" ] 28 | # Test whether command-line argument is present (non-empty). 29 | then 30 | lines=$1 31 | else 32 | lines=$LINES # Default, if not specified on command-line. 33 | fi 34 | 35 | 36 | # Stephane Chazelas suggests the following, 37 | #+ as a better way of checking command-line arguments, 38 | #+ but this is still a bit advanced for this stage of the tutorial. 39 | # 40 | # E_WRONGARGS=85 # Non-numerical argument (bad argument format). 41 | # 42 | # case "$1" in 43 | # "" ) lines=50;; 44 | # *[!0-9]*) echo "Usage: `basename $0` lines-to-cleanup"; 45 | # exit $E_WRONGARGS;; 46 | # * ) lines=$1;; 47 | # esac 48 | # 49 | #* Skip ahead to "Loops" chapter to decipher all this. 50 | 51 | 52 | cd $LOG_DIR 53 | 54 | if [ `pwd` != "$LOG_DIR" ] # or if [ "$PWD" != "$LOG_DIR" ] 55 | # Not in /var/log? 56 | then 57 | echo "Can't change to $LOG_DIR." 58 | exit $E_XCD 59 | fi # Doublecheck if in right directory before messing with log file. 60 | 61 | # Far more efficient is: 62 | # 63 | # cd /var/log || { 64 | # echo "Cannot change to necessary directory." >&2 65 | # exit $E_XCD; 66 | # } 67 | 68 | 69 | 70 | 71 | tail -n $lines messages > mesg.temp # Save last section of message log file. 72 | mv mesg.temp messages # Rename it as system log file. 73 | 74 | 75 | # cat /dev/null > messages 76 | #* No longer needed, as the above method is safer. 77 | 78 | cat /dev/null > wtmp # ': > wtmp' and '> wtmp' have the same effect. 79 | echo "Log files cleaned up." 80 | # Note that there are other log files in /var/log not affected 81 | #+ by this script. 82 | 83 | exit 0 84 | # A zero return value from the script upon exit indicates success 85 | #+ to the shell. 86 | -------------------------------------------------------------------------------- /tests/functions: -------------------------------------------------------------------------------- 1 | # -*-Shell-script-*- 2 | # 3 | # functions This file contains functions to be used by most or all 4 | # shell scripts in the /etc/init.d directory. 5 | # 6 | 7 | NORMAL="\\033[0;39m" # Standard console grey 8 | SUCCESS="\\033[1;32m" # Success is green 9 | WARNING="\\033[1;33m" # Warnings are yellow 10 | FAILURE="\\033[1;31m" # Failures are red 11 | INFO="\\033[1;36m" # Information is light cyan 12 | BRACKET="\\033[1;34m" # Brackets are blue 13 | 14 | # NOTE: The pidofproc () doesn't support the process which is a script unless 15 | # the pidof supports "-x" option. If you want to use it for such a 16 | # process: 17 | # 1) If there is no "pidof -x", replace the "pidof $1" with another 18 | # command like(for core-image-minimal): 19 | # ps | awk '/'"$1"'/ {print $1}' 20 | # Or 21 | # 2) If there is "pidof -x", replace "pidof" with "pidof -x". 22 | # 23 | # pidofproc - print the pid of a process 24 | # $1: the name of the process 25 | pidofproc () { 26 | 27 | # pidof output null when no program is running, so no "2>/dev/null". 28 | pid=`pidof $1` 29 | status=$? 30 | case $status in 31 | 0) 32 | echo $pid 33 | return 0 34 | ;; 35 | 127) 36 | echo "ERROR: command pidof not found" >&2 37 | exit 127 38 | ;; 39 | *) 40 | return $status 41 | ;; 42 | esac 43 | } 44 | 45 | machine_id() { # return the machine ID 46 | awk 'BEGIN { FS=": " } /Hardware/ \ 47 | { gsub(" ", "_", $2); print tolower($2) } ' /dev/null # Suppress output. 54 | then echo "Files a and b are identical." 55 | else echo "Files a and b differ." 56 | fi 57 | ##The very useful "if-grep" construct: 58 | ##----------------------------------- 59 | if grep -q Bash file 60 | then echo "File contains at least one occurrence of Bash." 61 | fi 62 | word=Linux 63 | letter_sequence=inu 64 | if echo "$word" | grep -q "$letter_sequence" 65 | ##The "-q" option to grep suppresses output. 66 | then 67 | echo "$letter_sequence found in $word" 68 | else 69 | echo "$letter_sequence not found in $word" 70 | fi 71 | # if COMMAND_WHOSE_EXIT_STATUS_IS_0_UNLESS_ERROR_OCCURRED 72 | # then echo "Command succeeded." 73 | # else echo "Command failed." 74 | # fi 75 | 76 | 77 | var1=5 78 | var2=4 79 | if (( var1 > var2 )) 80 | then #^ ^ Note: Not $var1, $var2. Why? 81 | echo "$var1 is greater than $var2" 82 | fi # 5 is greater than 4 83 | # exit 0 84 | 85 | hostname -b -F /etc/hostname 2> /dev/null 86 | if [ $? -eq 0 ]; then 87 | exit 88 | fi 89 | 90 | 91 | # if [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" -o ! -z "`echo $HOSTNAME | sed -n '/^[0-9]*\.[0-9].*/p'`" ] ; then 92 | # hostname localhost 93 | #fi 94 | 95 | 96 | read TIMESTAMP < "$TIMESTAMP_FILE" 97 | if [ ${TIMESTAMP} -gt $SYSTEMDATE ]; then 98 | echo "hello" 99 | fi 100 | 101 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '21 10 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'javascript' ] 32 | # language: [ 'cpp', 'javascript' ] 33 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 34 | # Learn more: 35 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 36 | 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v2 40 | 41 | # Initializes the CodeQL tools for scanning. 42 | - name: Initialize CodeQL 43 | uses: github/codeql-action/init@v1 44 | with: 45 | languages: ${{ matrix.language }} 46 | # If you wish to specify custom queries, you can do so here or in a config file. 47 | # By default, queries listed here will override any specified in a config file. 48 | # Prefix the list here with "+" to use these queries and those in the config file. 49 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 50 | 51 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 52 | # If this step fails, then you should remove it and run the build manually (see below) 53 | - name: Autobuild 54 | uses: github/codeql-action/autobuild@v1 55 | 56 | # ℹ️ Command-line programs to run using the OS shell. 57 | # 📚 https://git.io/JvXDl 58 | 59 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 60 | # and modify them (or add more) to build your code if your project 61 | # uses a compiled language 62 | 63 | #- run: | 64 | # make bootstrap 65 | # make release 66 | 67 | - name: Perform CodeQL Analysis 68 | uses: github/codeql-action/analyze@v1 69 | -------------------------------------------------------------------------------- /tests/exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void execcommand(const std::string &cmd, int& exitstatus, std::string &result, std::string &msg, int direction = 0, bool stdout = true, bool quoteparams=false) 13 | { 14 | std::string cmd_ = cmd; 15 | size_t offset = cmd_.find(" "); 16 | if (offset !=std::string::npos) { 17 | if (quoteparams) 18 | cmd_ = cmd_.substr(0, offset) + " \"" + cmd_.substr(offset + 1, std::string::npos) + "\""; 19 | } 20 | int in[2]; 21 | int link[2]; 22 | int control[2]; 23 | pid_t pid; 24 | 25 | if (pipe(control)==-1) 26 | perror("pipe"); 27 | 28 | if (pipe(link)==-1) 29 | perror("pipe"); 30 | 31 | if (pipe(in)==-1) 32 | perror("pipe"); 33 | 34 | if ((pid = fork()) == -1) 35 | perror("fork"); 36 | 37 | if(pid == 0) { 38 | int ret; 39 | 40 | dup2 (in[1], STDIN_FILENO); 41 | dup2 (link[1], STDOUT_FILENO); 42 | dup2 (link[1], STDERR_FILENO); 43 | close(in[1]); 44 | close(link[1]); 45 | 46 | ret = execle(cmd_.c_str(), cmd_.c_str(), NULL); 47 | // ret = system(cmd_.c_str()); 48 | write(control[1], &ret, sizeof(ret)); 49 | exit(ret); 50 | } 51 | else { 52 | if (msg.size() > 0) { 53 | write(in[0], msg.data(), msg.size()); 54 | } 55 | 56 | int ret; 57 | 58 | int nbytes = read(control[0], &ret, sizeof(ret)); 59 | if (!ret) 60 | { 61 | int bytesAvailable; 62 | ret = ioctl(link[0], FIONREAD, &bytesAvailable); 63 | if (ret) 64 | perror("ioctl"); 65 | 66 | std::array buffer; 67 | 68 | for (int i = 0; i < bytesAvailable / buffer.size(); i++) 69 | { 70 | auto bytes = read(link[0], buffer.data(), buffer.size()); 71 | result.append(buffer.data(), bytes); 72 | } 73 | if (bytesAvailable % buffer.size()) { 74 | auto bytes = read(link[0], buffer.data(), bytesAvailable % buffer.size()); 75 | result.append(buffer.data(), bytesAvailable % buffer.size()); 76 | } 77 | 78 | if (stdout) 79 | std::cout << result; 80 | } 81 | exitstatus = ret; 82 | close(in[0]); 83 | close(in[1]); 84 | close(link[0]); 85 | close(link[1]); 86 | close(control[0]); 87 | close(control[1]); 88 | } 89 | } 90 | 91 | int main() { 92 | std::string result; 93 | std::string out = "echo hello"; 94 | int exitstatus; 95 | execcommand("cat", exitstatus, result, out); 96 | return 0; 97 | } -------------------------------------------------------------------------------- /tests/5.2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # escaped.sh: escaped characters 3 | 4 | ############################################################# 5 | ### First, let's show some basic escaped-character usage. ### 6 | ############################################################# 7 | 8 | # Escaping a newline. 9 | # ------------------ 10 | 11 | echo "" 12 | 13 | echo "This will print 14 | as two lines." 15 | # This will print 16 | # as two lines. 17 | 18 | echo "This will print \ 19 | as one line." 20 | # This will print as one line. 21 | 22 | echo; echo 23 | 24 | echo "=============" 25 | 26 | 27 | echo "\v\v\v\v" # Prints \v\v\v\v literally. 28 | # Use the -e option with 'echo' to print escaped characters. 29 | echo "=============" 30 | echo "VERTICAL TABS" 31 | echo -e "\v\v\v\v" # Prints 4 vertical tabs. 32 | echo "==============" 33 | 34 | echo "QUOTATION MARK" 35 | echo -e "\042" # Prints " (quote, octal ASCII character 42). 36 | echo "==============" 37 | 38 | 39 | 40 | # The $'\X' construct makes the -e option unnecessary. 41 | 42 | echo; echo "NEWLINE and (maybe) BEEP" 43 | echo $'\n' # Newline. 44 | echo $'\a' # Alert (beep). 45 | # May only flash, not beep, depending on terminal. 46 | 47 | # We have seen $'\nnn" string expansion, and now . . . 48 | 49 | # =================================================================== # 50 | # Version 2 of Bash introduced the $'\nnn' string expansion construct. 51 | # =================================================================== # 52 | 53 | echo "Introducing the \$\' ... \' string-expansion construct . . . " 54 | echo ". . . featuring more quotation marks." 55 | 56 | echo $'\t \042 \t' # Quote (") framed by tabs. 57 | # Note that '\nnn' is an octal value. 58 | 59 | # It also works with hexadecimal values, in an $'\xhhh' construct. 60 | echo $'\t \x22 \t' # Quote (") framed by tabs. 61 | # Thank you, Greg Keraunen, for pointing this out. 62 | # Earlier Bash versions allowed '\x022'. 63 | 64 | echo 65 | 66 | 67 | # Assigning ASCII characters to a variable. 68 | # ---------------------------------------- 69 | quote=$'\042' # " assigned to a variable. 70 | echo "$quote Quoted string $quote and this lies outside the quotes." 71 | 72 | echo 73 | 74 | # Concatenating ASCII chars in a variable. 75 | triple_underline=$'\137\137\137' # 137 is octal ASCII code for '_'. 76 | echo "$triple_underline UNDERLINE $triple_underline" 77 | 78 | echo 79 | 80 | ABC=$'\101\102\103\010' # 101, 102, 103 are octal A, B, C. 81 | echo $ABC 82 | 83 | echo 84 | 85 | escape=$'\033' # 033 is octal for escape. 86 | echo "\"escape\" echoes as $escape" 87 | # no visible output. 88 | 89 | echo 90 | 91 | exit 0 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /tests/7.1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Tip: 4 | # If you're unsure how a certain condition might evaluate, 5 | #+ test it in an if-test. 6 | 7 | echo 8 | 9 | echo "Testing \"0\"" 10 | if [ 0 ] # zero 11 | then 12 | echo "0 is true." 13 | else # Or else ... 14 | echo "0 is false." 15 | fi # 0 is true. 16 | 17 | echo 18 | 19 | echo "Testing \"1\"" 20 | if [ 1 ] # one 21 | then 22 | echo "1 is true." 23 | else 24 | echo "1 is false." 25 | fi # 1 is true. 26 | 27 | echo 28 | 29 | echo "Testing \"-1\"" 30 | if [ -1 ] # minus one 31 | then 32 | echo "-1 is true." 33 | else 34 | echo "-1 is false." 35 | fi # -1 is true. 36 | 37 | echo 38 | 39 | echo "Testing \"NULL\"" 40 | if [ ] # NULL (empty condition) 41 | then 42 | echo "NULL is true." 43 | else 44 | echo "NULL is false." 45 | fi # NULL is false. 46 | 47 | echo 48 | 49 | echo "Testing \"xyz\"" 50 | if [ xyz ] # string 51 | then 52 | echo "Random string is true." 53 | else 54 | echo "Random string is false." 55 | fi # Random string is true. 56 | 57 | echo 58 | 59 | echo "Testing \"\$xyz\"" 60 | if [ $xyz ] # Tests if $xyz is null, but... 61 | # it's only an uninitialized variable. 62 | then 63 | echo "Uninitialized variable is true." 64 | else 65 | echo "Uninitialized variable is false." 66 | fi # Uninitialized variable is false. 67 | 68 | echo 69 | 70 | echo "Testing \"-n \$xyz\"" 71 | if [ -n "$xyz" ] # More pedantically correct. 72 | then 73 | echo "Uninitialized variable is true." 74 | else 75 | echo "Uninitialized variable is false." 76 | fi # Uninitialized variable is false. 77 | 78 | echo 79 | 80 | 81 | xyz= # Initialized, but set to null value. 82 | 83 | echo "Testing \"-n \$xyz\"" 84 | if [ -n "$xyz" ] 85 | then 86 | echo "Null variable is true." 87 | else 88 | echo "Null variable is false." 89 | fi # Null variable is false. 90 | 91 | 92 | echo 93 | 94 | 95 | # When is "false" true? 96 | 97 | echo "Testing \"false\"" 98 | if [ "false" ] # It seems that "false" is just a string ... 99 | then 100 | echo "\"false\" is true." #+ and it tests true. 101 | else 102 | echo "\"false\" is false." 103 | fi # "false" is true. 104 | 105 | echo 106 | 107 | echo "Testing \"\$false\"" # Again, uninitialized variable. 108 | if [ "$false" ] 109 | then 110 | echo "\"\$false\" is true." 111 | else 112 | echo "\"\$false\" is false." 113 | fi # "$false" is false. 114 | # Now, we get the expected result. 115 | 116 | # What would happen if we tested the uninitialized variable "$true"? 117 | 118 | echo 119 | 120 | exit 0 -------------------------------------------------------------------------------- /tests/9.7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Erratic behavior of the "$*" and "$@" internal Bash variables, 4 | #+ depending on whether or not they are quoted. 5 | # Demonstrates inconsistent handling of word splitting and linefeeds. 6 | 7 | 8 | set -- "First one" "second" "third:one" "" "Fifth: :one" 9 | # Setting the script arguments, $1, $2, $3, etc. 10 | 11 | echo 12 | 13 | echo 'IFS unchanged, using "$*"' 14 | c=0 15 | for i in "$*" # quoted 16 | do echo "$((c+=1)): [$i]" # This line remains the same in every instance. 17 | # Echo args. 18 | done 19 | echo --- 20 | 21 | echo 'IFS unchanged, using $*' 22 | c=0 23 | for i in $* # unquoted 24 | do echo "$((c+=1)): [$i]" 25 | done 26 | echo --- 27 | 28 | echo 'IFS unchanged, using "$@"' 29 | c=0 30 | for i in "$@" 31 | do echo "$((c+=1)): [$i]" 32 | done 33 | echo --- 34 | 35 | echo 'IFS unchanged, using $@' 36 | c=0 37 | for i in $@ 38 | do echo "$((c+=1)): [$i]" 39 | done 40 | echo --- 41 | 42 | IFS=: 43 | echo 'IFS=":", using "$*"' 44 | c=0 45 | for i in "$*" 46 | do echo "$((c+=1)): [$i]" 47 | done 48 | echo --- 49 | 50 | echo 'IFS=":", using $*' 51 | c=0 52 | for i in $* 53 | do echo "$((c+=1)): [$i]" 54 | done 55 | echo --- 56 | 57 | var=$* 58 | echo 'IFS=":", using "$var" (var=$*)' 59 | c=0 60 | for i in "$var" 61 | do echo "$((c+=1)): [$i]" 62 | done 63 | echo --- 64 | 65 | echo 'IFS=":", using $var (var=$*)' 66 | c=0 67 | for i in $var 68 | do echo "$((c+=1)): [$i]" 69 | done 70 | echo --- 71 | 72 | var="$*" 73 | echo 'IFS=":", using $var (var="$*")' 74 | c=0 75 | for i in $var 76 | do echo "$((c+=1)): [$i]" 77 | done 78 | echo --- 79 | 80 | echo 'IFS=":", using "$var" (var="$*")' 81 | c=0 82 | for i in "$var" 83 | do echo "$((c+=1)): [$i]" 84 | done 85 | echo --- 86 | 87 | echo 'IFS=":", using "$@"' 88 | c=0 89 | for i in "$@" 90 | do echo "$((c+=1)): [$i]" 91 | done 92 | echo --- 93 | 94 | echo 'IFS=":", using $@' 95 | c=0 96 | for i in $@ 97 | do echo "$((c+=1)): [$i]" 98 | done 99 | echo --- 100 | 101 | var=$@ 102 | echo 'IFS=":", using $var (var=$@)' 103 | c=0 104 | for i in $var 105 | do echo "$((c+=1)): [$i]" 106 | done 107 | echo --- 108 | 109 | echo 'IFS=":", using "$var" (var=$@)' 110 | c=0 111 | for i in "$var" 112 | do echo "$((c+=1)): [$i]" 113 | done 114 | echo --- 115 | 116 | var="$@" 117 | echo 'IFS=":", using "$var" (var="$@")' 118 | c=0 119 | for i in "$var" 120 | do echo "$((c+=1)): [$i]" 121 | done 122 | echo --- 123 | 124 | echo 'IFS=":", using $var (var="$@")' 125 | c=0 126 | for i in $var 127 | do echo "$((c+=1)): [$i]" 128 | done 129 | 130 | echo 131 | 132 | # Try this script with ksh or zsh -y. 133 | 134 | exit 0 135 | 136 | # This example script written by Stephane Chazelas, 137 | #+ and slightly modified by the document author. -------------------------------------------------------------------------------- /tests/case0.sh: -------------------------------------------------------------------------------- 1 | space=44 2 | echo "$space" 3 | case $space in 4 | [1-6]*) 5 | Message="All is quiet." 6 | ;; 7 | [7-8]*) 8 | Message="Start thinking about cleaning out some stuff. There's a partition that is $space % full." 9 | ;; 10 | 9[1-8]) 11 | Message="Better hurry with that new disk... One partition is $space % full." 12 | ;; 13 | 99) 14 | Message="I'm drowning here! There's a partition at $space %!" 15 | ;; 16 | *) 17 | Message="I seem to be running with an nonexistent amount of disk space..." 18 | ;; 19 | esac 20 | echo $Message 21 | 22 | space=70 23 | echo "$space" 24 | case $space in 25 | [1-6]*) 26 | Message="All is quiet." 27 | ;; 28 | [7-8]*) 29 | Message="Start thinking about cleaning out some stuff. There is a partition that is $space % full." 30 | ;; 31 | 9[1-8]) 32 | Message="Better hurry with that new disk... One partition is $space % full." 33 | ;; 34 | 99) 35 | Message="I'm drowning here! There's a partition at $space %!" 36 | ;; 37 | *) 38 | Message="I seem to be running with an nonexistent amount of disk space..." 39 | ;; 40 | esac 41 | echo $Message 42 | 43 | space=91 44 | echo "$space" 45 | case $space in 46 | [1-6]*) 47 | Message="All is quiet." 48 | ;; 49 | [7-8]*) 50 | Message="Start thinking about cleaning out some stuff. There's a partition that is $space % full." 51 | ;; 52 | 9[1-8]) 53 | Message="Better hurry with that new disk... One partition is $space % full." 54 | ;; 55 | 99) 56 | Message="I'm drowning here! There's a partition at $space %!" 57 | ;; 58 | *) 59 | Message="I seem to be running with an nonexistent amount of disk space..." 60 | ;; 61 | esac 62 | echo $Message 63 | 64 | space="" 65 | echo "$space" 66 | case $space in 67 | [1-6]*) 68 | Message="All is quiet." 69 | ;; 70 | [7-8]*) 71 | Message="Start thinking about cleaning out some stuff. There's a partition that is $space % full." 72 | ;; 73 | 9[1-8]) 74 | Message="Better hurry with that new disk... One partition is $space % full." 75 | ;; 76 | 99) 77 | Message="I'm drowning here! There's a partition at $space %!" 78 | ;; 79 | *) 80 | Message="I seem to be running with an nonexistent amount of disk space..." 81 | ;; 82 | esac 83 | echo $Message 84 | 85 | n=0 86 | case $n in 87 | 101) 88 | echo "You got 1st prize" ;; 89 | 510) 90 | echo "You got 2nd prize" ;; 91 | 999) 92 | echo "You got 3rd prize" ;; 93 | *) 94 | echo "Sorry, try for the next time" ;; 95 | esac 96 | 97 | n=101 98 | case $n in 99 | 101) 100 | echo "You got 1st prize" ;; 101 | 510) 102 | echo "You got 2nd prize" ;; 103 | 999) 104 | echo "You got 3rd prize" ;; 105 | *) 106 | echo "Sorry, try for the next time" ;; 107 | esac 108 | 109 | n=510 110 | case $n in 111 | 101) 112 | echo "You got 1st prize" ;; 113 | 510) 114 | echo "You got 2nd prize" ;; 115 | 999) 116 | echo "You got 3rd prize" ;; 117 | *) 118 | echo "Sorry, try for the next time" ;; 119 | esac 120 | 121 | n=999 122 | case $n in 123 | 101) 124 | echo "You got 1st prize" ;; 125 | 510) 126 | echo "You got 2nd prize" ;; 127 | 999) 128 | echo "You got 3rd prize" ;; 129 | *) 130 | echo "Sorry, try for the next time" ;; 131 | esac 132 | -------------------------------------------------------------------------------- /tests/expansions.sh: -------------------------------------------------------------------------------- 1 | echo "foo $((42 * 42)) baz" 2 | echo '$((42 * 42))' 3 | echo="ciao mondo" 4 | echo TEST=1 5 | ! echo run | echo cry 6 | variable=$(echo \\`echo ciao\\`) 7 | echo $variable 8 | echo world 9 | 10 | variable=$((42 + 43)) $ciao 11 | echo $variable 12 | 13 | echoword=$# 14 | echoword=$@ 15 | 16 | (echo) 17 | ( ls ) 18 | 19 | TEST1=1 TEST2=2 echo world 20 | 21 | until true; do sleep 1; done 22 | 23 | ls $var > gen/res.txt 24 | 25 | variable=$((42 + 43)) 26 | echo \'$((42 * 42))\' 27 | echo "\\$(\\(42 * 42))" 28 | variable=$((42 + 43)) $ciao 29 | echo $((42 + 43)) 30 | variable=$((42 + 43)) 31 | echo world 32 | echo \\\n\\\n\\\n\\\nthere 33 | 34 | TEST=1 echo run 35 | TEST=1 36 | 37 | echo run && echo stop 38 | echo run || echo cry 39 | echo run | echo cry 40 | ! echo run | echo cry 41 | echo TEST=1 42 | 43 | TEST1=1 TEST2=2 echo world 44 | echo; echo nls; 45 | { echo; ls; } 46 | { echo; ls; } > file.txt 47 | echo world > file.txt < input.dat 48 | { echo; ls; } > file.txt < input.dat 49 | echo;ls 50 | echo&ls 51 | echo && ls & 52 | echo && ls & echo ciao 53 | 54 | 55 | ls > file.txt 56 | command foo --lol 57 | ls 2> file.txt 58 | ( ls ) 59 | text=$(ls) 60 | echo ${text:2:4} 61 | echo ${!text*} 62 | echo ${!text@} 63 | echo ${text:2} 64 | echo ${var/a/b} 65 | echo ${var//a/b} 66 | echo ${!text[*]} 67 | echo ${!text[@]} 68 | echo ${text^t} 69 | echo ${text^^t} 70 | echo ${text,t} 71 | echo ${text,,t} 72 | echo ${text^} 73 | echo ${text^^} 74 | echo ${text,} 75 | echo ${text,,} 76 | echo ${text@Q} 77 | echo ${text@E} 78 | echo ${text@P} 79 | echo ${text@A} 80 | echo ${text@a} 81 | echo ${!text} 82 | 83 | 84 | variable=$(echo ciao) 85 | echo \'`echo ciao`\' 86 | echo $(echo ciao) 87 | echo `echo ciao` 88 | 89 | variable=$(echo ciao) 90 | variable=`echo ciao` 91 | variable=$(echo \\`echo ciao\\`) 92 | echo () { printf %s\\n "$*" ; } 93 | 94 | for x in a b c; do echo $x; done 95 | for x in; do echo $x; done 96 | if true; then echo 1; fi 97 | if true; then echo 1; else echo 2; fi 98 | if true; then echo 1; elif false; then echo 3; else echo 2; fi 99 | 100 | a=1 b=2 echo 101 | echo 102 | ls | grep *.js 103 | echo 42 43 104 | 105 | echo > 43 106 | echo 2> 43 107 | a=1 b=2 echo 42 43 108 | until true || 1; do sleep 1;echo ciao; done 109 | echo 110 | (echo) 111 | echo; echo ciao; 112 | echo 42 113 | echoword=${other}test 114 | echo "\\$ciao" 115 | echo "\\${ciao}" 116 | echo foo ${other} bar baz 117 | echo word${other}test 118 | echo word${other}t$est 119 | $other 120 | 121 | echoword=$@ 122 | echoword=$* 123 | echoword=$# 124 | echoword=$? 125 | echoword=$- 126 | echoword=$$ 127 | echoword=$! 128 | echoword=$0 129 | default_value=1 130 | value=2 131 | # other= 132 | # ${other:-default_value} 133 | # ${other-default_value} 134 | # ${#default_value} 135 | # ${other:=default_value} 136 | # ${other=default_value} 137 | # ${other:=default$value} 138 | # ${other:?default_value} 139 | # ${other?default_value} 140 | # ${other:+default_value} 141 | # ${other+default_value} 142 | # ${other%default$value} 143 | # ${other#default$value} 144 | # ${other%%default$value} 145 | # ${other##default$value} 146 | 147 | echo say ${other} plz 148 | echo say "${other} plz" 149 | echo 150 | a=echo 151 | echoword=$1ciao 152 | echoword=${11}test 153 | echoword=$1 154 | echoword=$11 -------------------------------------------------------------------------------- /tests/for0.sh: -------------------------------------------------------------------------------- 1 | PKGS="php7-openssl-7.3.19-r0 php7-common-7.3.19-r0 php7-fpm-7.3.19-r0 php7-opcache-7.3.19-r0 php7-7.3.19-r0" 2 | for p in $PKGS 3 | do 4 | echo "Installing $p package" 5 | done 6 | 7 | VALS="one two three four five" 8 | 9 | # a simple For loop iterates with space separators. 10 | for ITEM in $VALS 11 | do 12 | 13 | echo "value: $ITEM" 14 | 15 | done 16 | 17 | users='2323dad sdad tj' 18 | for user in ${users}; do 19 | echo ${user} 20 | done 21 | 22 | 23 | for ITEM in {10..1..-2}; do 24 | 25 | echo "count: $ITEM" 26 | 27 | done 28 | 29 | i=1 30 | for day in Mon Tue Wed Thu Fri 31 | do 32 | echo "Weekday $day" 33 | done 34 | 35 | for i in {a..z} 36 | do 37 | echo $i 38 | done 39 | 40 | for i in 1 2 3 4; do 41 | echo $i 42 | done 43 | 44 | 45 | for ITEM in {5..1}; do 46 | 47 | echo "count: $ITEM" 48 | 49 | done 50 | 51 | 52 | for ITEM in $VALS; do 53 | 54 | echo "value: $ITEM" 55 | 56 | done 57 | 58 | for i in $(seq 1 2 20) 59 | do 60 | echo "Welcome $i times" 61 | done 62 | 63 | for i in {1..5} 64 | do 65 | echo "Welcome $i times" 66 | done 67 | 68 | 69 | echo "Content of this directory:" 70 | dir_content=$(ls) 71 | for name in $dir_content; do 72 | echo $name 73 | done 74 | 75 | for f in *.ts; do echo "Processing $f file.."; done 76 | 77 | for OUTPUT in $(ls) 78 | do 79 | echo $OUTPUT 80 | done 81 | 82 | for f in tests/*.sh 83 | do 84 | echo "Removing password for pdf file - $f" 85 | done 86 | 87 | 88 | # Loop current directory content which is received using ls command and then 89 | # each line is echoed back to stdout. 90 | 91 | # Parse error on line 92: Unexpected 'OPEN_PAREN' 92 | for (( counter=100; counter>=1; counter-- )); 93 | do 94 | echo $counter 95 | done 96 | 97 | # Parse error on line 92: Unexpected 'OPEN_PAREN' 98 | LIMIT=5 99 | for (( IDX = 1; IDX <= $LIMIT; IDX++ )); do 100 | echo "count: $IDX" 101 | done 102 | 103 | 104 | START=10 105 | END=1 106 | INCREMENT=-2 107 | 108 | for ITEM in $( seq $START $INCREMENT $END ); do 109 | echo "count: $ITEM" 110 | done 111 | 112 | 113 | START=1 114 | END=10 115 | 116 | for ITEM in $( seq $START $END ); do 117 | echo "count: $ITEM" 118 | done 119 | 120 | # Parse error on line 92: Unexpected 'OPEN_PAREN' 121 | VALS=( 'five' 'four' 'three' 'two' 'one' ) 122 | 123 | # A For loop that iterates through a formal array. Note the [@] referend 124 | # in ITEMS, this is represents *every* entry in the array, much like $@ 125 | # represents the entirety of the command line arguments. Also note that 126 | # there can be no spaces between the array variable and the curly braces 127 | # that surround it within the quotes. 128 | for ITEM in "${VALS[@]}"; do 129 | 130 | echo "value: $ITEM" 131 | 132 | done 133 | 134 | # bash prints on a single line 135 | # weekdays="Mon Tue Wed Thu Fri" 136 | # for day in "$weekdays" 137 | # do 138 | # echo "Weekday $day" 139 | # done 140 | 141 | 142 | # Echo list with , deviced 143 | list='2323dad,sdad,tj' 144 | IFS=, 145 | for item in ${list}; do 146 | echo ${item} 147 | done 148 | 149 | # Echo range numbers 150 | for num in {1..10}; do 151 | echo ${num} 152 | done 153 | 154 | generate_list () 155 | { 156 | echo "one two three" 157 | } 158 | 159 | for word in $(generate_list) # Let "word" grab output of function. 160 | do 161 | echo "$word" 162 | done 163 | -------------------------------------------------------------------------------- /tests/4.1.sh: -------------------------------------------------------------------------------- 1 | !/bin/bash 2 | # ex9.sh 3 | 4 | # Variables: assignment and substitution 5 | 6 | a=375 7 | hello=$a 8 | # ^ ^ 9 | 10 | #------------------------------------------------------------------------- 11 | # No space permitted on either side of = sign when initializing variables. 12 | # What happens if there is a space? 13 | 14 | # "VARIABLE =value" 15 | # ^ 16 | #% Script tries to run "VARIABLE" command with one argument, "=value". 17 | 18 | # "VARIABLE= value" 19 | # ^ 20 | #% Script tries to run "value" command with 21 | #+ the environmental variable "VARIABLE" set to "". 22 | #------------------------------------------------------------------------- 23 | 24 | 25 | echo hello # hello 26 | # Not a variable reference, just the string "hello" ... 27 | 28 | echo $hello # 375 29 | # ^ This *is* a variable reference. 30 | echo ${hello} # 375 31 | # Likewise a variable reference, as above. 32 | 33 | # Quoting . . . 34 | echo "$hello" # 375 35 | echo "${hello}" # 375 36 | 37 | echo 38 | 39 | hello="A B C D" 40 | echo $hello # A B C D 41 | echo "$hello" # A B C D 42 | # As we see, echo $hello and echo "$hello" give different results. 43 | # ======================================= 44 | # Quoting a variable preserves whitespace. 45 | # ======================================= 46 | 47 | echo 48 | 49 | echo '$hello' # $hello 50 | # ^ ^ 51 | # Variable referencing disabled (escaped) by single quotes, 52 | #+ which causes the "$" to be interpreted literally. 53 | 54 | # Notice the effect of different types of quoting. 55 | 56 | 57 | hello= # Setting it to a null value. 58 | echo "\$hello (null value) = $hello" # $hello (null value) = 59 | # Note that setting a variable to a null value is not the same as 60 | #+ unsetting it, although the end result is the same (see below). 61 | 62 | # -------------------------------------------------------------- 63 | 64 | # It is permissible to set multiple variables on the same line, 65 | #+ if separated by white space. 66 | # Caution, this may reduce legibility, and may not be portable. 67 | 68 | var1=21 var2=22 var3=$V3 69 | echo 70 | echo "var1=$var1 var2=$var2 var3=$var3" 71 | 72 | # May cause problems with legacy versions of "sh" . . . 73 | 74 | # -------------------------------------------------------------- 75 | 76 | echo; echo 77 | 78 | numbers="one two three" 79 | # ^ ^ 80 | other_numbers="1 2 3" 81 | # ^ ^ 82 | # If there is whitespace embedded within a variable, 83 | #+ then quotes are necessary. 84 | # other_numbers=1 2 3 # Gives an error message. 85 | echo "numbers = $numbers" 86 | echo "other_numbers = $other_numbers" # other_numbers = 1 2 3 87 | # Escaping the whitespace also works. 88 | mixed_bag=2\ ---\ Whatever 89 | # ^ ^ Space after escape (\). 90 | 91 | echo "$mixed_bag" # 2 --- Whatever 92 | 93 | echo; echo 94 | 95 | echo "uninitialized_variable = $uninitialized_variable" 96 | # Uninitialized variable has null value (no value at all!). 97 | uninitialized_variable= # Declaring, but not initializing it -- 98 | #+ same as setting it to a null value, as above. 99 | echo "uninitialized_variable = $uninitialized_variable" 100 | # It still has a null value. 101 | 102 | uninitialized_variable=23 # Set it. 103 | unset uninitialized_variable # Unset it. 104 | echo "uninitialized_variable = $uninitialized_variable" 105 | # uninitialized_variable = 106 | # It still has a null value. 107 | echo 108 | 109 | exit 0 110 | -------------------------------------------------------------------------------- /bash2cpp.njsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14.0 4 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 5 | bash2cpp 6 | bash2cpp 7 | tests/tildaexpansion.sh gen/tildaexpansion.cpp 8 | True 9 | 10 | 11 | 12 | Debug 13 | 2.0 14 | 00fc0137-5ee7-43f1-8e56-45a0f9ed5a37 15 | . 16 | app.ts 17 | False 18 | 19 | 20 | . 21 | . 22 | v4.0 23 | {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} 24 | true 25 | False 26 | 27 | 28 | true 29 | 30 | 31 | true 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | False 45 | True 46 | 0 47 | / 48 | http://localhost:48022/ 49 | False 50 | True 51 | http://localhost:1337 52 | False 53 | 54 | 55 | 56 | 57 | 58 | 59 | CurrentPage 60 | True 61 | False 62 | False 63 | False 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | False 73 | False 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /tests/checkroot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: checkroot 4 | # Required-Start: udev 5 | # Required-Stop: 6 | # Default-Start: S 7 | # Default-Stop: 8 | # Short-Description: Check to root file system. 9 | ### END INIT INFO 10 | 11 | . /etc/default/rcS 12 | 13 | # 14 | # Set SULOGIN in /etc/default/rcS to yes if you want a sulogin to be spawned 15 | # from this script *before anything else* with a timeout, like SCO does. 16 | # 17 | test "$SULOGIN" = yes && sulogin -t 30 $CONSOLE 18 | 19 | # 20 | # Read /etc/fstab. 21 | # 22 | exec 9< /etc/fstab 23 | rootmode=rw 24 | rootopts=rw 25 | rootcheck=$ENABLE_ROOTFS_FSCK 26 | swap_on_md=no 27 | devfs= 28 | while read fs mnt type opts dump pass junk <&9 29 | do 30 | case "$fs" in 31 | ""|\#*) 32 | continue; 33 | ;; 34 | /dev/md*) 35 | # Swap on md device. 36 | test "$type" = swap && swap_on_md=yes 37 | ;; 38 | /dev/*) 39 | ;; 40 | *) 41 | # Might be a swapfile. 42 | test "$type" = swap && swap_on_md=yes 43 | ;; 44 | esac 45 | test "$type" = devfs && devfs="$fs" 46 | test "$mnt" != / && continue 47 | rootopts="$opts" 48 | test "$pass" = 0 -o "$pass" = "" && rootcheck=no 49 | case "$opts" in 50 | ro|ro,*|*,ro|*,ro,*) 51 | rootmode=ro 52 | ;; 53 | esac 54 | done 55 | exec 0>&9 9>&- 56 | 57 | # Check for conflicting configurations 58 | if [ "$rootmode" = "ro" -a "$ROOTFS_READ_ONLY" = "no" ] || \ 59 | [ "$rootmode" = "rw" -a "$ROOTFS_READ_ONLY" = "yes" ]; then 60 | echo "" 61 | echo "WARN: conflicting configurations in /etc/fstab and /etc/default/rcS" 62 | echo " regarding the writability of rootfs. Please fix one of them." 63 | echo "" 64 | fi 65 | 66 | 67 | # 68 | # Activate the swap device(s) in /etc/fstab. This needs to be done 69 | # before fsck, since fsck can be quite memory-hungry. 70 | # 71 | test "$VERBOSE" != no && echo "Activating swap" 72 | [ -x /sbin/swapon ] && swapon -a 73 | 74 | # 75 | # Check the root filesystem. 76 | # 77 | if test -f /fastboot || test $rootcheck = no 78 | then 79 | test $rootcheck = yes && echo "Fast boot, no filesystem check" 80 | else 81 | # 82 | # Ensure that root is quiescent and read-only before fsck'ing. 83 | # 84 | mount -n -o remount,ro / 85 | if test $? = 0 86 | then 87 | if test -f /forcefsck 88 | then 89 | force="-f" 90 | else 91 | force="" 92 | fi 93 | if test "$FSCKFIX" = yes 94 | then 95 | fix="-y" 96 | else 97 | fix="-a" 98 | fi 99 | spinner="-C" 100 | case "$TERM" in 101 | dumb|network|unknown|"") spinner="" ;; 102 | esac 103 | test `uname -m` = s390 && spinner="" # This should go away 104 | test "$VERBOSE" != no && echo "Checking root filesystem..." 105 | fsck $spinner $force $fix / 106 | # 107 | # If there was a failure, drop into single-user mode. 108 | # 109 | # NOTE: "failure" is defined as exiting with a return code of 110 | # 2 or larger. A return code of 1 indicates that filesystem 111 | # errors were corrected but that the boot may proceed. 112 | # 113 | if test "$?" -gt 1 114 | then 115 | # Surprise! Re-directing from a HERE document (as in 116 | # "cat << EOF") won't work, because the root is read-only. 117 | echo 118 | echo "fsck failed. Please repair manually and reboot. Please note" 119 | echo "that the root filesystem is currently mounted read-only. To" 120 | echo "remount it read-write:" 121 | echo 122 | echo " # mount -n -o remount,rw /" 123 | echo 124 | echo "CONTROL-D will exit from this shell and REBOOT the system." 125 | echo 126 | # Start a single user shell on the console 127 | /sbin/sulogin $CONSOLE 128 | reboot -f 129 | fi 130 | else 131 | echo "*** ERROR! Cannot fsck root fs because it is not mounted read-only!" 132 | echo 133 | fi 134 | fi 135 | 136 | # 137 | # If the root filesystem was not marked as read-only in /etc/fstab, 138 | # remount the rootfs rw but do not try to change mtab because it 139 | # is on a ro fs until the remount succeeded. Then clean up old mtabs 140 | # and finally write the new mtab. 141 | # 142 | mount -n -o remount,$rootmode / 143 | if test "$rootmode" = rw 144 | then 145 | ln -sf /proc/mounts /dev/mtab 146 | fi 147 | 148 | : exit 0 149 | -------------------------------------------------------------------------------- /tests/if2.sh: -------------------------------------------------------------------------------- 1 | if [ -n "$v" ] 2 | # Test whether command-line argument is present (non-empty). 3 | then 4 | echo "variable not defined" 5 | else 6 | echo "variable defined" 7 | fi 8 | 9 | n=10 10 | if [ $n -lt 10 ]; 11 | then 12 | echo "It is a one digit number" 13 | else 14 | echo "It is a two digit number" 15 | fi 16 | 17 | n=101 18 | if [ $n -eq 101 ]; 19 | then 20 | echo "You got 1st prize" 21 | elif [ $n -eq 510 ]; 22 | then 23 | echo "You got 2nd prize" 24 | elif [ $n -eq 999 ]; 25 | then 26 | echo "You got 3rd prize" 27 | else 28 | echo "Sorry, try for the next time" 29 | fi 30 | 31 | n=510 32 | if [ $n -eq 101 ]; 33 | then 34 | echo "You got 1st prize" 35 | elif [ $n -eq 510 ]; 36 | then 37 | echo "You got 2nd prize" 38 | elif [ $n -eq 999 ]; 39 | then 40 | echo "You got 3rd prize" 41 | else 42 | echo "Sorry, try for the next time" 43 | fi 44 | 45 | n=999 46 | if [ $n -eq 101 ]; 47 | then 48 | echo "You got 1st prize" 49 | elif [ $n -eq 510 ]; 50 | then 51 | echo "You got 2nd prize" 52 | elif [ $n -eq 999 ]; 53 | then 54 | echo "You got 3rd prize" 55 | else 56 | echo "Sorry, try for the next time" 57 | fi 58 | 59 | n=0 60 | if [ $n -eq 101 ]; 61 | then 62 | echo "You got 1st prize" 63 | elif [ $n -eq 510 ]; 64 | then 65 | echo "You got 2nd prize" 66 | elif [ $n -eq 999 ]; 67 | then 68 | echo "You got 3rd prize" 69 | else 70 | echo "Sorry, try for the next time" 71 | fi 72 | 73 | if ! wget -q --spider --tries=10 --timeout=20 google.com 74 | then 75 | echo 'Sorry you are Offline' 76 | else 77 | echo "you are online" 78 | fi 79 | 80 | VAR='' 81 | # if [ -z ${VAR+x} ]; 82 | # then 83 | # echo "CHECK 1: variable 'VAR' is unset"; 84 | # else 85 | # echo "CHECK 1: variable 'VAR' is set, its content is '$VAR'"; 86 | # fi 87 | 88 | ROOT_UID=0 89 | if [ "$UID" -ne "$ROOT_UID" ]; 90 | then 91 | echo "Must be root to run this script." 92 | fi 93 | 94 | file=/etc/passwd 95 | if [[ -e $file ]] 96 | then 97 | echo "Password file exists." 98 | fi 99 | 100 | 101 | if [ $xyz ] # Tests if $xyz is null, but... 102 | # it's only an uninitialized variable. 103 | then 104 | echo "Uninitialized variable is true." 105 | else 106 | echo "Uninitialized variable is false." 107 | fi # Uninitialized variable is false. 108 | 109 | if [ ] # zero 110 | then 111 | echo "empty is true." 112 | else # Or else ... 113 | echo "empty is false." 114 | fi # empty is false. 115 | 116 | if [ 0 ] # zero 117 | then 118 | echo "0 is true." 119 | else # Or else ... 120 | echo "0 is false." 121 | fi # 0 is true. 122 | 123 | if [ "" ] # zero 124 | then 125 | echo "0 is true." 126 | else # Or else ... 127 | echo "0 is false." 128 | fi # 0 is true. 129 | 130 | if [ -n "$xyz" ] # More pedantically correct. 131 | then 132 | echo "Uninitialized variable is true." 133 | else 134 | echo "Uninitialized variable is false." 135 | fi # Uninitialized variable is false. 136 | 137 | if [ "true" ] # It seems that "false" is just a string ... 138 | then 139 | echo "true is true." #+ and it tests true. 140 | else 141 | echo "true is false." 142 | fi # "false" is true. 143 | 144 | if [ "$UID" -eq "$ROOT_UID" ] 145 | then 146 | echo "You are root." 147 | else 148 | echo "You are not root" 149 | fi 150 | 151 | num=0 152 | if [[ $num -gt 10 ]] 153 | then 154 | echo "Number is greater than 10." 155 | elif [[ $num -eq 10 ]] 156 | then 157 | echo "Number is equal to 10." 158 | else 159 | echo "Number is less than 10." 160 | fi 161 | 162 | num=11 163 | if [[ $num -gt 10 ]] 164 | then 165 | echo "Number is greater than 10." 166 | elif [[ $num -eq 10 ]] 167 | then 168 | echo "Number is equal to 10." 169 | else 170 | echo "Number is less than 10." 171 | fi 172 | 173 | num=10 174 | if [[ $num -gt 10 ]] 175 | then 176 | echo "Number is greater than 10." 177 | elif [[ $num -eq 10 ]] 178 | then 179 | echo "Number is equal to 10." 180 | else 181 | echo "Number is less than 10." 182 | fi 183 | 184 | n=15 185 | if [[ $n -eq 15 || $n -eq 45 ]] 186 | then 187 | echo "You won" 188 | else 189 | echo "You lost!" 190 | fi 191 | 192 | n=45 193 | if [[ $n -eq 15 || $n -eq 45 ]] 194 | then 195 | echo "You won" 196 | else 197 | echo "You lost!" 198 | fi 199 | 200 | n=30 201 | if [[ $n -eq 15 || $n -eq 45 ]] 202 | then 203 | echo "You won" 204 | else 205 | echo "You lost!" 206 | fi 207 | 208 | filename="app.js" 209 | if [ -f "$filename" ]; then 210 | echo "File exists" 211 | else 212 | echo "File does not exist" 213 | fi 214 | 215 | filename="app.js1" 216 | if [ -f "$filename" ]; then 217 | echo "File exists" 218 | else 219 | echo "File does not exist" 220 | fi 221 | 222 | ndir="gen" 223 | if [ -d "$ndir" ] 224 | then 225 | echo "Directory exist" 226 | else 227 | echo "Directory does not exit" 228 | fi 229 | 230 | ndir="gen1" 231 | if [ -d "$ndir" ] 232 | then 233 | echo "Directory exist" 234 | else 235 | echo "Directory does not exit" 236 | fi 237 | -------------------------------------------------------------------------------- /tests/exec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #define PIPE_READ 0 23 | #define PIPE_WRITE 1 24 | 25 | int createChild(int *outfd, std::vector &aArguments, std::string &result, bool stdout, bool resultcollect) { 26 | int aStdinPipe[2]; 27 | int aStdoutPipe[2]; 28 | int nChild; 29 | char nChar; 30 | int nResult; 31 | 32 | if (pipe(aStdinPipe) < 0) { 33 | return -1; 34 | } 35 | if (pipe(aStdoutPipe) < 0) { 36 | close(aStdinPipe[PIPE_READ]); 37 | close(aStdinPipe[PIPE_WRITE]); 38 | return -1; 39 | } 40 | 41 | nChild = fork(); 42 | if (0 == nChild) { 43 | close(outfd[0]); 44 | if (dup2(outfd[1], STDOUT_FILENO) == -1) { 45 | printf("%s:%d\n", __func__, __LINE__); 46 | exit(errno); 47 | } 48 | 49 | if (dup2(outfd[1], STDERR_FILENO) == -1) { 50 | printf("%s:%d\n", __func__, __LINE__); 51 | exit(errno); 52 | } 53 | close(aStdinPipe[PIPE_READ]); 54 | close(aStdinPipe[PIPE_WRITE]); 55 | close(aStdoutPipe[PIPE_READ]); 56 | close(aStdoutPipe[PIPE_WRITE]); 57 | 58 | nResult = execvpe(aArguments[0], &aArguments[0], environ); 59 | 60 | exit(nResult); 61 | } else if (nChild > 0) { 62 | close(outfd[1]); 63 | close(aStdinPipe[PIPE_READ]); 64 | close(aStdoutPipe[PIPE_WRITE]); 65 | close(aStdinPipe[PIPE_WRITE]); 66 | close(aStdoutPipe[PIPE_READ]); 67 | 68 | int rc; 69 | if (waitpid(nChild, &rc, 0) != -1) { 70 | if (WIFEXITED(rc)) { 71 | nChild = WEXITSTATUS(rc); 72 | } 73 | } 74 | } else { 75 | close(aStdinPipe[PIPE_READ]); 76 | close(aStdinPipe[PIPE_WRITE]); 77 | close(aStdoutPipe[PIPE_READ]); 78 | close(aStdoutPipe[PIPE_WRITE]); 79 | } 80 | return nChild; 81 | } 82 | 83 | void execcommand(int *outfd, const std::string_view &cmd, int & exitstatus, std::string &result, bool stdout = true, bool resultcollect = true) 84 | { 85 | std::vector toks; 86 | wordexp_t p; 87 | char **w; 88 | int ret; 89 | 90 | ret = wordexp(cmd.data(), &p, 0); 91 | if (ret) { 92 | printf("%s:%d\n", __func__, __LINE__); 93 | exit(-1); 94 | }; 95 | w = p.we_wordv; 96 | toks.reserve(p.we_wordc); 97 | for (int i = 0; i < p.we_wordc; i++) { 98 | toks.emplace_back(w[i]); 99 | } 100 | toks.push_back(NULL); 101 | exitstatus = createChild(outfd, toks, result, stdout, resultcollect); 102 | wordfree(&p); 103 | } 104 | 105 | const std::string exec(const std::string_view &cmd, bool collectresults = true) { 106 | int exitstatus; 107 | std::string result; 108 | int outfd[2]; 109 | 110 | pipe(outfd); 111 | execcommand(outfd, cmd, exitstatus, result, true, collectresults); 112 | 113 | size_t available = 0; 114 | const int bufsize = 512; 115 | char databuf[bufsize + 1]; 116 | databuf[bufsize] = 0; 117 | char nChar; 118 | 119 | while (read(outfd[0], &nChar, 1) == 1) { 120 | if (stdout) 121 | write(STDOUT_FILENO, &nChar, 1); 122 | if (collectresults) result += nChar; 123 | 124 | ioctl(outfd[0], FIONREAD, &available); 125 | if (available && collectresults) result.reserve(available + 2); 126 | while (available / bufsize) { 127 | read(outfd[0], &databuf[0], bufsize); 128 | if (stdout) 129 | write(STDOUT_FILENO, &databuf[0], bufsize); 130 | if (collectresults) result += databuf; 131 | available -= bufsize; 132 | } 133 | if (available % bufsize) { 134 | read(outfd[0], &databuf[0], available % bufsize); 135 | databuf[available % bufsize] = 0; 136 | if (stdout) 137 | write(STDOUT_FILENO, &databuf[0], available % bufsize); 138 | if (collectresults) result += databuf; 139 | } 140 | } 141 | close(outfd[0]); 142 | return result; 143 | } 144 | 145 | const void execnoresult(const std::string_view &cmd) { 146 | int exitstatus; 147 | std::string result; 148 | int outfd[2]; 149 | 150 | pipe(outfd); 151 | execcommand(outfd, cmd, exitstatus, result, true, false); 152 | } 153 | 154 | const std::string execnoout(const std::string_view &cmd, bool collectresults = true) { 155 | int exitstatus; 156 | std::string result; 157 | int outfd[2]; 158 | 159 | pipe(outfd); 160 | execcommand(outfd, cmd, exitstatus, result, false, collectresults); 161 | return result; 162 | } 163 | 164 | 165 | int main(int argc, const char *argv[]) { 166 | exec("cat tests/fstab"); 167 | return 0; 168 | } 169 | -------------------------------------------------------------------------------- /tests/if0.sh: -------------------------------------------------------------------------------- 1 | VAR="variable" 2 | 3 | # variables can also be used within the 4 | # conditional statements. 5 | case "variable" in 6 | 7 | $VAR) 8 | echo "You should see this text!" 9 | ;; 10 | 11 | *) 12 | echo "You should NOT see this text!" 13 | ;; 14 | 15 | esac 16 | 17 | # this conditional tests that the given variable 18 | # is not an empty string. 19 | if [ ! -z $VAR ]; then # the -z stands for zero, as in zero content. 20 | 21 | echo "You should see this text!" 22 | 23 | else 24 | 25 | echo "You should NOT see this text!" 26 | 27 | fi 28 | 29 | 30 | if [ ! -e /proc ]; then 31 | mount -t proc proc /proc 32 | echo "proc not mounted" 33 | else 34 | echo "proc already mounted" 35 | fi 36 | 37 | 38 | count=100 39 | 40 | if [ $count -eq 100 ]; 41 | then 42 | echo "Count is $count" 43 | fi 44 | 45 | count=120 46 | 47 | if [ $count -eq 100 ] 48 | then 49 | echo "Count is 100" 50 | else 51 | if [ $count -gt 100 ] 52 | then 53 | echo "Count is greater than 100" 54 | else 55 | echo "Count is less than 100" 56 | fi 57 | fi 58 | 59 | count=12 60 | 61 | if [ $count -eq 100 ] 62 | then 63 | echo "Count is 100" 64 | elif [ $count -gt 100 ] 65 | then 66 | echo "Count is greater than 100" 67 | else 68 | echo "Count is less than 100" 69 | fi 70 | 71 | aNumber="2" 72 | if [ $aNumber -lt 3 ] 73 | then 74 | echo "$aNumber is less than 3" 75 | else 76 | echo "$aNumber is greater than or equal to 3" 77 | fi 78 | 79 | aNumber="4" 80 | if (($aNumber < 3)) 81 | then 82 | echo "$aNumber is less than 3" 83 | else 84 | echo "$aNumber is greater than or equal to 3" 85 | fi 86 | 87 | 88 | VAR="variable" 89 | 90 | # In each of the statements below, note the space between 91 | # the 'if' and the '[' as well as the space before the ']' 92 | # this spacing is REQUIRED! 93 | 94 | # verify that $VAR equals 'variable' 95 | if [ $VAR == "variable" ] 96 | then 97 | 98 | echo "You should see this text!" 99 | 100 | fi 101 | 102 | # this is the same IF statement. 103 | # The comma after the ']' is usee to separate the conditional from 104 | # the 'then' keyword, which is ecpected to be on a different line. 105 | if [ $VAR == "variable" ]; then 106 | 107 | echo "You should see this text!" 108 | 109 | fi 110 | 111 | # Also, if no operation is to be performed, a placeholder 112 | # must be used, otherwise an exception will be thrown. 113 | if [ $VAR == "variable" ]; then 114 | : 115 | fi 116 | 117 | 118 | # ------------------------------------- 119 | 120 | 121 | # an ELSE statement can be added as well. 122 | if [ $VAR == "variable" ]; then 123 | 124 | echo "You should see this text!" 125 | 126 | else 127 | 128 | echo "You should NOT see this text!" 129 | 130 | fi 131 | 132 | 133 | # ------------------------------------- 134 | 135 | 136 | # inequality can be tested as such. 137 | if [ $VAR != "variable" ]; then 138 | 139 | echo "You should NOT see this text!" 140 | 141 | else 142 | 143 | echo "You should see this text!" 144 | 145 | fi 146 | 147 | 148 | # ------------------------------------- 149 | 150 | 151 | # Special flags can also be used. For example, 152 | # this conditional tests that the given variable 153 | # is an empty string. 154 | if [ -z $VAR ]; then # the -z stands for zero, as in zero content. 155 | 156 | echo "You should NOT see this text!" 157 | 158 | else 159 | 160 | echo "You should see this text!" 161 | 162 | fi 163 | 164 | # this conditional tests that the given variable 165 | # is a file and actually exists. 166 | if [ -e $VAR ]; then # the -e stands for EXISTS.. 167 | 168 | echo "You should NOT see this text!" 169 | 170 | else 171 | 172 | echo "You should see this text!" 173 | 174 | fi 175 | 176 | # this conditional tests that the given variable 177 | # is a directory and actually exists. 178 | if [ -d $VAR ]; then # the -e stands for EXISTS.. 179 | 180 | echo "You should NOT see this text!" 181 | 182 | else 183 | 184 | echo "You should see this text!" 185 | 186 | fi 187 | 188 | 189 | # ------------------------------------- 190 | 191 | 192 | # this conditional tests that the given variable 193 | # is not an empty string. 194 | if [ ! -z $VAR ]; then # the -z stands for zero, as in zero content. 195 | 196 | echo "You should see this text!" 197 | 198 | else 199 | 200 | echo "You should NOT see this text!" 201 | 202 | fi 203 | 204 | 205 | # ------------------------------------- 206 | 207 | 208 | # conditionals can also be expressed in the form 209 | # of 'case' statements, much like the switch-case 210 | # statements used in many programming languages. 211 | 212 | # note that each condition ends in ';;'. This is 213 | # the equivalent of a 'break' statement, as used 214 | # in other programming languages like C, Java, etc. 215 | 216 | echo "$VAR" 217 | 218 | case "$VAR" in 219 | 220 | "var") 221 | echo "You should NOT see this text!" 222 | ;; 223 | 224 | "value") 225 | echo "You should NOT see this text!" 226 | ;; 227 | 228 | "variable") 229 | echo "You should see this text!" 230 | ;; 231 | 232 | esac 233 | 234 | exit 0 235 | 236 | # also, see that the quotes around each 237 | # string condition are optional. 238 | 239 | # additionally, a default catch-all condition can 240 | # be added for situations where none of the explict 241 | # conditions meet the expected conditions. 242 | 243 | case "$VAR" in 244 | 245 | var) 246 | echo "You should NOT see this text!" 247 | ;; 248 | 249 | value) 250 | echo "You should NOT see this text!" 251 | ;; 252 | 253 | *) 254 | echo "You should see this text!" 255 | ;; 256 | 257 | esac 258 | 259 | # variables can also be used within the 260 | # conditional statements. 261 | case "variable" in 262 | 263 | $VAR) 264 | echo "You should see this text!" 265 | ;; 266 | 267 | *) 268 | echo "You should NOT see this text!" 269 | ;; 270 | 271 | esac 272 | 273 | # as with 'if' statements, blocks can be used 274 | # in cases where no operation is to be executed. 275 | case "$VAR" in 276 | 277 | *) 278 | : 279 | 280 | esac 281 | -------------------------------------------------------------------------------- /tests/pipe2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define PIPE_READ 0 25 | #define PIPE_WRITE 1 26 | 27 | extern char** environ; 28 | 29 | int createChild(std::vector &aArguments) { 30 | int aStdinPipe[2]; 31 | int aStdoutPipe[2]; 32 | int nChild; 33 | char nChar; 34 | int nResult; 35 | 36 | if (pipe(aStdinPipe) < 0) { 37 | perror("allocating pipe for child input redirect"); 38 | return -1; 39 | } 40 | if (pipe(aStdoutPipe) < 0) { 41 | close(aStdinPipe[PIPE_READ]); 42 | close(aStdinPipe[PIPE_WRITE]); 43 | perror("allocating pipe for child output redirect"); 44 | return -1; 45 | } 46 | 47 | nChild = fork(); 48 | if (0 == nChild) { 49 | if (dup2(aStdoutPipe[PIPE_WRITE], STDOUT_FILENO) == -1) { 50 | exit(errno); 51 | } 52 | 53 | if (dup2(aStdoutPipe[PIPE_WRITE], STDERR_FILENO) == -1) { 54 | exit(errno); 55 | } 56 | 57 | close(aStdinPipe[PIPE_READ]); 58 | close(aStdinPipe[PIPE_WRITE]); 59 | close(aStdoutPipe[PIPE_READ]); 60 | close(aStdoutPipe[PIPE_WRITE]); 61 | 62 | nResult = execvpe(aArguments[0], &aArguments[0], environ); 63 | 64 | exit(nResult); 65 | } else if (nChild > 0) { 66 | close(aStdinPipe[PIPE_READ]); 67 | close(aStdoutPipe[PIPE_WRITE]); 68 | 69 | while (read(aStdoutPipe[PIPE_READ], &nChar, 1) == 1) { 70 | std::cout << nChar; 71 | } 72 | 73 | close(aStdinPipe[PIPE_WRITE]); 74 | close(aStdoutPipe[PIPE_READ]); 75 | 76 | int rc; 77 | if (waitpid(nChild, &rc, 0) != -1) { 78 | if (WIFEXITED(rc)) { 79 | nChild = WEXITSTATUS(rc); 80 | } 81 | } 82 | } else { 83 | close(aStdinPipe[PIPE_READ]); 84 | close(aStdinPipe[PIPE_WRITE]); 85 | close(aStdoutPipe[PIPE_READ]); 86 | close(aStdoutPipe[PIPE_WRITE]); 87 | } 88 | return nChild; 89 | } 90 | 91 | int execWrapper(std::string str) 92 | { 93 | std::vector toks; 94 | wordexp_t p; 95 | char **w; 96 | int ret; 97 | 98 | wordexp(str.c_str(), &p, 0); 99 | w = p.we_wordv; 100 | for (int i = 0; i < p.we_wordc; i++) { 101 | toks.push_back(w[i]); 102 | } 103 | toks.push_back(NULL); 104 | 105 | ret = createChild(toks); 106 | wordfree(&p); 107 | return ret; 108 | } 109 | 110 | void testCall() 111 | { 112 | std::streambuf *backupout0 = std::cout.rdbuf(); 113 | std::streambuf *backupin0 = std::cin.rdbuf(); 114 | std::stringstream redirectStream0; 115 | std::cout.rdbuf(redirectStream0.rdbuf()); 116 | // execWrapper("df /dev/sda"); 117 | execWrapper("echo hello"); 118 | std::cout.rdbuf(backupout0); 119 | std::cout << redirectStream0.str(); 120 | 121 | std::cin.rdbuf(backupin0); 122 | 123 | 124 | std::streambuf *backupout1 = std::cout.rdbuf(); 125 | std::streambuf *backupin1 = std::cin.rdbuf(); 126 | std::stringstream redirectStream1; 127 | std::cout.rdbuf(redirectStream1.rdbuf()); 128 | std::cin.rdbuf(redirectStream0.rdbuf()); 129 | // execWrapper("awk '/^\//{print $3}'"); 130 | execWrapper("wc"); 131 | // exec(get_env("AWK") + " " + "'/^\\//{print $3}'",true, false); 132 | std::cout.rdbuf(backupout1); 133 | 134 | std::cin.rdbuf(backupin1); 135 | // return redirectStream1 136 | std::cout << redirectStream1.str(); 137 | } 138 | 139 | class scopeexitcinfile { 140 | int m_backup; 141 | int m_redirectStream; 142 | public: 143 | scopeexitcinfile(const std::string &file) { 144 | m_redirectStream = open(file.c_str(), O_RDONLY); 145 | m_backup = dup(0); 146 | if (m_redirectStream >= 0) { 147 | dup2(m_redirectStream, STDIN_FILENO); 148 | close(m_redirectStream); 149 | } 150 | } 151 | ~scopeexitcinfile() { 152 | dup2(m_backup, 0); 153 | close(m_backup); 154 | } 155 | }; 156 | 157 | class scopeexitcincout { 158 | 159 | std::streambuf *backupout = std::cout.rdbuf(); 160 | std::streambuf *backupin = std::cin.rdbuf(); 161 | std::stringstream buffer; 162 | int readfd[2]; 163 | int m_inbackup; 164 | bool m_released = false; 165 | 166 | public: 167 | 168 | ~scopeexitcincout() { 169 | release(); 170 | } 171 | scopeexitcincout() { 172 | std::cout.rdbuf(buffer.rdbuf()); 173 | pipe(readfd); 174 | m_inbackup = dup(0); 175 | dup2(readfd[0], STDIN_FILENO); 176 | close(readfd[0]); 177 | } 178 | 179 | std::string buf() { return buffer.str();} 180 | 181 | void release() { 182 | if (m_released) return; 183 | 184 | std::cout.rdbuf(backupout); 185 | std::cin.rdbuf(backupin); 186 | dup2(m_inbackup, 0); 187 | close(m_inbackup); 188 | m_released = true; 189 | } 190 | 191 | void writecin(std::string &str) { 192 | write(readfd[1], str.data(), str.size()); 193 | close(readfd[1]); 194 | } 195 | }; 196 | 197 | class scopeexitcoutfile { 198 | std::streambuf *m_backup; 199 | std::ofstream m_redirectStream; 200 | public: 201 | scopeexitcoutfile(const std::string &file, bool append = false) { 202 | append ? m_redirectStream = std::ofstream(file, std::ios_base::app): m_redirectStream = std::ofstream(file); 203 | m_backup = std::cout.rdbuf(); 204 | if (m_redirectStream) std::cout.rdbuf(m_redirectStream.rdbuf()); 205 | } 206 | ~scopeexitcoutfile() { 207 | std::cout.rdbuf(m_backup); 208 | } 209 | }; 210 | 211 | class scopeexitcerrfile { 212 | std::streambuf *m_backup; 213 | std::ofstream m_redirectStream; 214 | public: 215 | scopeexitcerrfile(const std::string &file, bool append = false) { 216 | append ? m_redirectStream = std::ofstream(file, std::ios_base::app): m_redirectStream = std::ofstream(file); 217 | m_backup = std::cerr.rdbuf(); 218 | if (m_redirectStream) std::cerr.rdbuf(m_redirectStream.rdbuf()); 219 | } 220 | ~scopeexitcerrfile() { 221 | std::cerr.rdbuf(m_backup); 222 | } 223 | }; 224 | 225 | int main() 226 | { 227 | std::string text; 228 | { 229 | scopeexitcincout scope; 230 | std::string str("hello"); 231 | scope.writecin(str); 232 | execWrapper("wc"); 233 | text = scope.buf(); 234 | } 235 | std::cout << text << std::endl; 236 | exit(0); 237 | execWrapper("echo hello"); 238 | // testCall(); 239 | { 240 | scopeexitcoutfile scopeout("out.txt"); 241 | scopeexitcinfile scope("in.txt"); 242 | execWrapper("wc"); 243 | } 244 | 245 | return 0; 246 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | a.out 7 | out0.txt 8 | out1.txt 9 | 10 | # User-specific files 11 | *.rsuser 12 | *.suo 13 | *.user 14 | *.js 15 | *.map 16 | *.userosscache 17 | *.sln.docstates 18 | 19 | # User-specific files (MonoDevelop/Xamarin Studio) 20 | *.userprefs 21 | 22 | # Build results 23 | [Dd]ebug/ 24 | [Dd]ebugPublic/ 25 | [Rr]elease/ 26 | [Rr]eleases/ 27 | x64/ 28 | x86/ 29 | [Aa][Rr][Mm]/ 30 | [Aa][Rr][Mm]64/ 31 | bld/ 32 | [Bb]in/ 33 | [Oo]bj/ 34 | [Ll]og/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUNIT 49 | *.VisualState.xml 50 | TestResult.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # StyleCop 66 | StyleCopReport.xml 67 | 68 | # Files built by Visual Studio 69 | *_i.c 70 | *_p.c 71 | *_h.h 72 | *.ilk 73 | *.meta 74 | *.obj 75 | *.iobj 76 | *.pch 77 | *.pdb 78 | *.ipdb 79 | *.pgc 80 | *.pgd 81 | *.rsp 82 | *.sbr 83 | *.tlb 84 | *.tli 85 | *.tlh 86 | *.tmp 87 | *.tmp_proj 88 | *_wpftmp.csproj 89 | *.log 90 | *.vspscc 91 | *.vssscc 92 | .builds 93 | *.pidb 94 | *.svclog 95 | *.scc 96 | 97 | # Chutzpah Test files 98 | _Chutzpah* 99 | 100 | # Visual C++ cache files 101 | ipch/ 102 | *.aps 103 | *.ncb 104 | *.opendb 105 | *.opensdf 106 | *.sdf 107 | *.cachefile 108 | *.VC.db 109 | *.VC.VC.opendb 110 | 111 | # Visual Studio profiler 112 | *.psess 113 | *.vsp 114 | *.vspx 115 | *.sap 116 | 117 | # Visual Studio Trace Files 118 | *.e2e 119 | 120 | # TFS 2012 Local Workspace 121 | $tf/ 122 | 123 | # Guidance Automation Toolkit 124 | *.gpState 125 | 126 | # ReSharper is a .NET coding add-in 127 | _ReSharper*/ 128 | *.[Rr]e[Ss]harper 129 | *.DotSettings.user 130 | 131 | # JustCode is a .NET coding add-in 132 | .JustCode 133 | 134 | # TeamCity is a build add-in 135 | _TeamCity* 136 | 137 | # DotCover is a Code Coverage Tool 138 | *.dotCover 139 | 140 | # AxoCover is a Code Coverage Tool 141 | .axoCover/* 142 | !.axoCover/settings.json 143 | 144 | # Visual Studio code coverage results 145 | *.coverage 146 | *.coveragexml 147 | 148 | # NCrunch 149 | _NCrunch_* 150 | .*crunch*.local.xml 151 | nCrunchTemp_* 152 | 153 | # MightyMoose 154 | *.mm.* 155 | AutoTest.Net/ 156 | 157 | # Web workbench (sass) 158 | .sass-cache/ 159 | 160 | # Installshield output folder 161 | [Ee]xpress/ 162 | 163 | # DocProject is a documentation generator add-in 164 | DocProject/buildhelp/ 165 | DocProject/Help/*.HxT 166 | DocProject/Help/*.HxC 167 | DocProject/Help/*.hhc 168 | DocProject/Help/*.hhk 169 | DocProject/Help/*.hhp 170 | DocProject/Help/Html2 171 | DocProject/Help/html 172 | 173 | # Click-Once directory 174 | publish/ 175 | 176 | # Publish Web Output 177 | *.[Pp]ublish.xml 178 | *.azurePubxml 179 | # Note: Comment the next line if you want to checkin your web deploy settings, 180 | # but database connection strings (with potential passwords) will be unencrypted 181 | *.pubxml 182 | *.publishproj 183 | 184 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 185 | # checkin your Azure Web App publish settings, but sensitive information contained 186 | # in these scripts will be unencrypted 187 | PublishScripts/ 188 | 189 | # NuGet Packages 190 | *.nupkg 191 | # The packages folder can be ignored because of Package Restore 192 | **/[Pp]ackages/* 193 | # except build/, which is used as an MSBuild target. 194 | !**/[Pp]ackages/build/ 195 | # Uncomment if necessary however generally it will be regenerated when needed 196 | #!**/[Pp]ackages/repositories.config 197 | # NuGet v3's project.json files produces more ignorable files 198 | *.nuget.props 199 | *.nuget.targets 200 | 201 | # Microsoft Azure Build Output 202 | csx/ 203 | *.build.csdef 204 | 205 | # Microsoft Azure Emulator 206 | ecf/ 207 | rcf/ 208 | 209 | # Windows Store app package directories and files 210 | AppPackages/ 211 | BundleArtifacts/ 212 | Package.StoreAssociation.xml 213 | _pkginfo.txt 214 | *.appx 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- Backup*.rdl 265 | 266 | # Microsoft Fakes 267 | FakesAssemblies/ 268 | 269 | # GhostDoc plugin setting file 270 | *.GhostDoc.xml 271 | 272 | # Node.js Tools for Visual Studio 273 | .ntvs_analysis.dat 274 | node_modules/ 275 | 276 | # Visual Studio 6 build log 277 | *.plg 278 | 279 | # Visual Studio 6 workspace options file 280 | *.opt 281 | 282 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 283 | *.vbw 284 | 285 | # Visual Studio LightSwitch build output 286 | **/*.HTMLClient/GeneratedArtifacts 287 | **/*.DesktopClient/GeneratedArtifacts 288 | **/*.DesktopClient/ModelManifest.xml 289 | **/*.Server/GeneratedArtifacts 290 | **/*.Server/ModelManifest.xml 291 | _Pvt_Extensions 292 | 293 | # Paket dependency manager 294 | .paket/paket.exe 295 | paket-files/ 296 | 297 | # FAKE - F# Make 298 | .fake/ 299 | 300 | # JetBrains Rider 301 | .idea/ 302 | *.sln.iml 303 | 304 | # CodeRush personal settings 305 | .cr/personal 306 | 307 | # Python Tools for Visual Studio (PTVS) 308 | __pycache__/ 309 | *.pyc 310 | 311 | # Cake - Uncomment if you are using it 312 | # tools/** 313 | # !tools/packages.config 314 | 315 | # Tabs Studio 316 | *.tss 317 | 318 | # Telerik's JustMock configuration file 319 | *.jmconfig 320 | 321 | # BizTalk build output 322 | *.btp.cs 323 | *.btm.cs 324 | *.odx.cs 325 | *.xsd.cs 326 | 327 | # OpenCover UI analysis results 328 | OpenCover/ 329 | 330 | # Azure Stream Analytics local run output 331 | ASALocalRun/ 332 | 333 | # MSBuild Binary and Structured Log 334 | *.binlog 335 | 336 | # NVidia Nsight GPU debugger configuration file 337 | *.nvuser 338 | 339 | # MFractors (Xamarin productivity tool) working folder 340 | .mfractor/ 341 | 342 | # Local History for Visual Studio 343 | .localhistory/ 344 | 345 | # BeatPulse healthcheck temp database 346 | healthchecksdb 347 | 348 | gen -------------------------------------------------------------------------------- /tests/populate-volatile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: volatile 4 | # Required-Start: $local_fs 5 | # Required-Stop: $local_fs 6 | # Default-Start: S 7 | # Default-Stop: 8 | # Short-Description: Populate the volatile filesystem 9 | ### END INIT INFO 10 | 11 | # Get ROOT_DIR 12 | DIRNAME=`dirname $0` 13 | ROOT_DIR=`echo $DIRNAME | sed -ne 's:/etc/.*::p'` 14 | 15 | [ -e ${ROOT_DIR}/etc/default/rcS ] && . ${ROOT_DIR}/etc/default/rcS 16 | # When running populate-volatile.sh at rootfs time, disable cache. 17 | [ -n "$ROOT_DIR" ] && VOLATILE_ENABLE_CACHE=no 18 | # If rootfs is read-only, disable cache. 19 | [ "$ROOTFS_READ_ONLY" = "yes" ] && VOLATILE_ENABLE_CACHE=no 20 | 21 | CFGDIR="${ROOT_DIR}/etc/default/volatiles" 22 | TMPROOT="${ROOT_DIR}/var/volatile/tmp" 23 | COREDEF="00_core" 24 | 25 | [ "${VERBOSE}" != "no" ] && echo "Populating volatile Filesystems." 26 | 27 | create_file() { 28 | EXEC="" 29 | [ -z "$2" ] && { 30 | EXEC=" 31 | touch \"$1\"; 32 | " 33 | } || { 34 | EXEC=" 35 | cp \"$2\" \"$1\"; 36 | " 37 | } 38 | EXEC=" 39 | ${EXEC} 40 | chown ${TUSER}:${TGROUP} $1 || echo \"Failed to set owner -${TUSER}- for -$1-.\" >/dev/tty0 2>&1; 41 | chmod ${TMODE} $1 || echo \"Failed to set mode -${TMODE}- for -$1-.\" >/dev/tty0 2>&1 " 42 | 43 | test "$VOLATILE_ENABLE_CACHE" = yes && echo "$EXEC" >> /etc/volatile.cache.build 44 | 45 | [ -e "$1" ] && { 46 | [ "${VERBOSE}" != "no" ] && echo "Target already exists. Skipping." 47 | } || { 48 | if [ -z "$ROOT_DIR" ]; then 49 | eval $EXEC 50 | else 51 | # Creating some files at rootfs time may fail and should fail, 52 | # but these failures should not be logged to make sure the do_rootfs 53 | # process doesn't fail. This does no harm, as this script will 54 | # run on target to set up the correct files and directories. 55 | eval $EXEC > /dev/null 2>&1 56 | fi 57 | } 58 | } 59 | 60 | mk_dir() { 61 | EXEC=" 62 | mkdir -p \"$1\"; 63 | chown ${TUSER}:${TGROUP} $1 || echo \"Failed to set owner -${TUSER}- for -$1-.\" >/dev/tty0 2>&1; 64 | chmod ${TMODE} $1 || echo \"Failed to set mode -${TMODE}- for -$1-.\" >/dev/tty0 2>&1 " 65 | 66 | test "$VOLATILE_ENABLE_CACHE" = yes && echo "$EXEC" >> /etc/volatile.cache.build 67 | [ -e "$1" ] && { 68 | [ "${VERBOSE}" != "no" ] && echo "Target already exists. Skipping." 69 | } || { 70 | if [ -z "$ROOT_DIR" ]; then 71 | eval $EXEC 72 | else 73 | # For the same reason with create_file(), failures should 74 | # not be logged. 75 | eval $EXEC > /dev/null 2>&1 76 | fi 77 | } 78 | } 79 | 80 | link_file() { 81 | EXEC=" 82 | if [ -L \"$2\" ]; then 83 | [ \"\$(readlink \"$2\")\" != \"$1\" ] && { rm -f \"$2\"; ln -sf \"$1\" \"$2\"; }; 84 | elif [ -d \"$2\" ]; then 85 | if awk '\$2 == \"$2\" {exit 1}' /proc/mounts; then 86 | cp -a $2/* $1 2>/dev/null; 87 | cp -a $2/.[!.]* $1 2>/dev/null; 88 | rm -rf \"$2\"; 89 | ln -sf \"$1\" \"$2\"; 90 | fi 91 | else 92 | ln -sf \"$1\" \"$2\"; 93 | fi 94 | " 95 | 96 | test "$VOLATILE_ENABLE_CACHE" = yes && echo " $EXEC" >> /etc/volatile.cache.build 97 | 98 | if [ -z "$ROOT_DIR" ]; then 99 | eval $EXEC 100 | else 101 | # For the same reason with create_file(), failures should 102 | # not be logged. 103 | eval $EXEC > /dev/null 2>&1 104 | fi 105 | } 106 | 107 | check_requirements() { 108 | cleanup() { 109 | rm "${TMP_INTERMED}" 110 | rm "${TMP_DEFINED}" 111 | rm "${TMP_COMBINED}" 112 | } 113 | 114 | CFGFILE="$1" 115 | 116 | TMP_INTERMED="${TMPROOT}/tmp.$$" 117 | TMP_DEFINED="${TMPROOT}/tmpdefined.$$" 118 | TMP_COMBINED="${TMPROOT}/tmpcombined.$$" 119 | 120 | sed 's@\(^:\)*:.*@\1@' ${ROOT_DIR}/etc/passwd | sort | uniq > "${TMP_DEFINED}" 121 | cat ${CFGFILE} | grep -v "^#" | cut -s -d " " -f 2 > "${TMP_INTERMED}" 122 | cat "${TMP_DEFINED}" "${TMP_INTERMED}" | sort | uniq > "${TMP_COMBINED}" 123 | NR_DEFINED_USERS="`cat "${TMP_DEFINED}" | wc -l`" 124 | NR_COMBINED_USERS="`cat "${TMP_COMBINED}" | wc -l`" 125 | 126 | [ "${NR_DEFINED_USERS}" -ne "${NR_COMBINED_USERS}" ] && { 127 | echo "Undefined users:" 128 | diff "${TMP_DEFINED}" "${TMP_COMBINED}" | grep "^>" 129 | cleanup 130 | return 1 131 | } 132 | 133 | 134 | sed 's@\(^:\)*:.*@\1@' ${ROOT_DIR}/etc/group | sort | uniq > "${TMP_DEFINED}" 135 | cat ${CFGFILE} | grep -v "^#" | cut -s -d " " -f 3 > "${TMP_INTERMED}" 136 | cat "${TMP_DEFINED}" "${TMP_INTERMED}" | sort | uniq > "${TMP_COMBINED}" 137 | 138 | NR_DEFINED_GROUPS="`cat "${TMP_DEFINED}" | wc -l`" 139 | NR_COMBINED_GROUPS="`cat "${TMP_COMBINED}" | wc -l`" 140 | 141 | [ "${NR_DEFINED_GROUPS}" -ne "${NR_COMBINED_GROUPS}" ] && { 142 | echo "Undefined groups:" 143 | diff "${TMP_DEFINED}" "${TMP_COMBINED}" | grep "^>" 144 | cleanup 145 | return 1 146 | } 147 | 148 | # Add checks for required directories here 149 | 150 | cleanup 151 | return 0 152 | } 153 | 154 | apply_cfgfile() { 155 | CFGFILE="$1" 156 | SKIP_REQUIREMENTS="$2" 157 | 158 | [ "${VERBOSE}" != "no" ] && echo "Applying ${CFGFILE}" 159 | 160 | [ "${SKIP_REQUIREMENTS}" == "yes" ] || check_requirements "${CFGFILE}" || { 161 | echo "Skipping ${CFGFILE}" 162 | return 1 163 | } 164 | 165 | cat ${CFGFILE} | sed 's/#.*//' | \ 166 | while read TTYPE TUSER TGROUP TMODE TNAME TLTARGET; do 167 | test -z "${TLTARGET}" && continue 168 | TNAME=${ROOT_DIR}${TNAME} 169 | [ "${VERBOSE}" != "no" ] && echo "Checking for -${TNAME}-." 170 | 171 | [ "${TTYPE}" = "l" ] && { 172 | TSOURCE="$TLTARGET" 173 | [ "${VERBOSE}" != "no" ] && echo "Creating link -${TNAME}- pointing to -${TSOURCE}-." 174 | link_file "${TSOURCE}" "${TNAME}" 175 | continue 176 | } 177 | 178 | [ "${TTYPE}" = "b" ] && { 179 | TSOURCE="$TLTARGET" 180 | [ "${VERBOSE}" != "no" ] && echo "Creating mount-bind -${TNAME}- from -${TSOURCE}-." 181 | mount --bind "${TSOURCE}" "${TNAME}" 182 | EXEC=" 183 | mount --bind \"${TSOURCE}\" \"${TNAME}\"" 184 | test "$VOLATILE_ENABLE_CACHE" = yes && echo "$EXEC" >> /etc/volatile.cache.build 185 | continue 186 | } 187 | 188 | [ -L "${TNAME}" ] && { 189 | [ "${VERBOSE}" != "no" ] && echo "Found link." 190 | NEWNAME=`ls -l "${TNAME}" | sed -e 's/^.*-> \(.*\)$/\1/'` 191 | echo ${NEWNAME} | grep -v "^/" >/dev/null && { 192 | TNAME="`echo ${TNAME} | sed -e 's@\(.*\)/.*@\1@'`/${NEWNAME}" 193 | [ "${VERBOSE}" != "no" ] && echo "Converted relative linktarget to absolute path -${TNAME}-." 194 | } || { 195 | TNAME="${NEWNAME}" 196 | [ "${VERBOSE}" != "no" ] && echo "Using absolute link target -${TNAME}-." 197 | } 198 | } 199 | 200 | case "${TTYPE}" in 201 | "f") [ "${VERBOSE}" != "no" ] && echo "Creating file -${TNAME}-." 202 | TSOURCE="$TLTARGET" 203 | [ "${TSOURCE}" = "none" ] && TSOURCE="" 204 | create_file "${TNAME}" "${TSOURCE}" & 205 | ;; 206 | "d") [ "${VERBOSE}" != "no" ] && echo "Creating directory -${TNAME}-." 207 | mk_dir "${TNAME}" 208 | # Add check to see if there's an entry in fstab to mount. 209 | ;; 210 | *) [ "${VERBOSE}" != "no" ] && echo "Invalid type -${TTYPE}-." 211 | continue 212 | ;; 213 | esac 214 | done 215 | return 0 216 | } 217 | 218 | clearcache=0 219 | exec 9&- 230 | 231 | if test -e ${ROOT_DIR}/etc/volatile.cache -a "$VOLATILE_ENABLE_CACHE" = "yes" -a "x$1" != "xupdate" -a "x$clearcache" = "x0" 232 | then 233 | sh ${ROOT_DIR}/etc/volatile.cache 234 | else 235 | rm -f ${ROOT_DIR}/etc/volatile.cache ${ROOT_DIR}/etc/volatile.cache.build 236 | 237 | # Apply the core file with out checking requirements. ${TMPROOT} is 238 | # needed by check_requirements but is setup by this file, so it must be 239 | # processed first and without being checked. 240 | [ -e "${CFGDIR}/${COREDEF}" ] && apply_cfgfile "${CFGDIR}/${COREDEF}" "yes" 241 | 242 | # Fast path: check_requirements is slow and most of the time doesn't 243 | # find any problems. If there are a lot of config files, it is much 244 | # faster to to concatenate them all together and process them once to 245 | # avoid the overhead of calling check_requirements repeatedly 246 | TMP_FILE="${TMPROOT}/tmp_volatile.$$" 247 | rm -f "$TMP_FILE" 248 | 249 | CFGFILES="`ls -1 "${CFGDIR}" | grep -v "^${COREDEF}\$" | sort`" 250 | for file in ${CFGFILES}; do 251 | cat "${CFGDIR}/${file}" >> "$TMP_FILE" 252 | done 253 | 254 | if check_requirements "$TMP_FILE" 255 | then 256 | apply_cfgfile "$TMP_FILE" "yes" 257 | else 258 | # Slow path: One or more config files failed requirements. 259 | # Process each one individually so the offending one can be 260 | # skipped 261 | for file in ${CFGFILES}; do 262 | apply_cfgfile "${CFGDIR}/${file}" 263 | done 264 | fi 265 | rm "$TMP_FILE" 266 | 267 | [ -e ${ROOT_DIR}/etc/volatile.cache.build ] && sync && mv ${ROOT_DIR}/etc/volatile.cache.build ${ROOT_DIR}/etc/volatile.cache 268 | fi 269 | 270 | if [ -z "${ROOT_DIR}" ] && [ -f /etc/ld.so.cache ] && [ ! -f /var/run/ld.so.cache ] 271 | then 272 | ln -s /etc/ld.so.cache /var/run/ld.so.cache 273 | fi 274 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # INTRODUCTION 2 | 3 | bash2cpp converts simple bash scripts to c++ code. 4 | It requires c++17 for file IO and expects c++ code to run in Linux. 5 | Code also uses boost::format for printf format specifier conversion. 6 | Though, with some effort Linux dependency can be removed but this is not 7 | in radar at this moment. 8 | 9 | 10 | Reasons why you may want to try bash2cpp are: 11 | 1. Faster execution time by using native binary as opposed to shell script. 12 | 2. Code obfiscuation to prevent modification. 13 | 14 | bash2cpp is not a complete translator but does a good job for simple scripts. 15 | 16 | ![CodeQL](https://github.com/franksinankaya/bash2cpp/workflows/CodeQL/badge.svg) 17 | 18 | ![Node.js CI](https://github.com/franksinankaya/bash2cpp/workflows/Node.js%20CI/badge.svg) 19 | 20 | # REQUIREMENTS 21 |
 22 | sudo apt-get install -y build-essential
 23 | sudo add-apt-repository ppa:ubuntu-toolchain-r/test
 24 | sudo apt update
 25 | sudo apt install gcc-9 g++-9
 26 | sudo update-alternatives \
 27 | --install /usr/bin/gcc gcc /usr/bin/gcc-9 100 \
 28 | --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-9 \
 29 | --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-9 \
 30 | --slave /usr/bin/gcov gcov /usr/bin/gcov-9
 31 | sudo update-alternatives \
 32 | --install /usr/bin/g++ g++ /usr/bin/g++-9 100
 33 | 
34 | curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - 35 | 36 | # INSTALLATION 37 | * git clone https://github.com/franksinankaya/bash2cpp.git 38 | * cd bash-parser 39 | * git submodule init 40 | * git submodule update 41 | * npm install --save-dev 42 | * npm run build 43 | 44 | # USAGE 45 | * mkdir -p gen 46 | * node app.js test.sh gen/test.cpp 47 | * optional (beautify code) 48 | * astyle -q -n gen/%test.cpp 49 | * if you have WSL 50 | * wsl g++ gen/test.cpp -o gen/test -lpcre -std=c++17 -g 51 | * if you are on linux 52 | * g++ gen/test.cpp -o gen/test -lpcre -std=c++17 -g 53 | * Size and speed optimization 54 | * g++ gen/test.cpp -o gen/test -lpcre -std=c++17 -O3 -ffunction-sections -fdata-sections -Wl,--gc-sections -flto -g 55 | # IMPROVEMENT 56 | 57 |
 58 | test                           bash                           native c++                     delta
 59 | ----------------------------------------------------------------------------------------------------
 60 | gen/for8                       0.00696563720703125            0.007452487945556641           6.532727621728838
 61 | gen/if10                       0.00515294075012207            0.004492282867431641           -14.70650674026112
 62 | gen/local                      0.006060123443603516           0.004212141036987305           -43.87275711779023
 63 | gen/default0                   0.007678508758544922           0.005669355392456055           -35.438832583371884
 64 | gen/functions3                 0.005850553512573242           0.004854679107666016           -20.513701993910225
 65 | gen/array0                     0.006394386291503906           0.004038572311401367           -58.332841371981814
 66 | gen/array                      0.006585597991943359           0.004456758499145508           -47.76654362595624
 67 | gen/for7                       0.007401227951049805           0.005717277526855469           -29.45371142618849
 68 | gen/for5                       0.007921695709228516           0.006716728210449219           -17.939798381371574
 69 | gen/for4                       0.007215738296508789           0.0057315826416015625          -25.89434276206323
 70 | gen/echo4                      0.006974697113037109           0.0045092105865478516          -54.67667741764924
 71 | gen/showsize                   0.017104625701904297           0.010923147201538086           -56.5906362545018
 72 | gen/upper                      0.006481170654296875           0.008647441864013672           25.05100634132892
 73 | gen/echo3                      0.007898569107055664           0.00489497184753418            -61.360868929910865
 74 | gen/lower0                     0.006561279296875              0.00459742546081543            -42.71638230565783
 75 | gen/upper0                     0.007020711898803711           0.0052280426025390625          -34.2894928858081
 76 | gen/echo2                      0.005777120590209961           0.004124164581298828           -40.07977800901838
 77 | gen/special                    0.006903886795043945           0.0061266422271728516          -12.686305794450714
 78 | gen/functions1                 0.010600566864013672           0.005499362945556641           -92.75990635567501
 79 | tests/arguments.sh 1 2 3       0.006421566009521484           0.006428956985473633           0.11496384201743
 80 | tests/arguments.sh 1           0.005584239959716797           0.004723072052001953           -18.233215547703182
 81 | gen/arguments                  0.007460594177246094           0.006247282028198242           -19.42144029309621
 82 | gen/for2                       0.008064746856689453           0.005383014678955078           -49.81840729914076
 83 | gen/tildaexpansion             0.007880449295043945           0.004729509353637695           -66.62297726470736
 84 | gen/echo1                      0.007907390594482422           0.00601649284362793            -31.428571428571427
 85 | gen/redirection0               0.032849788665771484           0.02049565315246582            -60.276856860350144
 86 | gen/while0                     0.015790462493896484           0.009736776351928711           -62.17341266926223
 87 | gen/for0                       0.0326693058013916             0.02129340171813965            -53.424550167392596
 88 | gen/braceexpansion             0.007658243179321289           0.005018949508666992           -52.586575459598116
 89 | gen/redirection                0.05733919143676758            0.038558006286621094           -48.70891147881576
 90 | gen/pipeline                   0.027769088745117188           0.027825117111206055           0.20135895875997156
 91 | gen/hostname0                  0.010652780532836914           0.008131980895996094           -30.99859270552363
 92 | gen/if9                        0.010847091674804688           0.008524656295776367           -27.243742133967277
 93 | gen/redirect                   0.047963857650756836           0.039482831954956055           -21.480287192864864
 94 | gen/while0                     0.00813913345336914            0.007466793060302734           -9.004406411648253
 95 | gen/if3                        0.009643316268920898           0.004790306091308594           -101.30897869798925
 96 | gen/if0                        0.0068531036376953125          0.006569385528564453           -4.318792189881687
 97 | gen/arithmetic                 0.015211105346679688           0.013452291488647461           -13.07445545256367
 98 | gen/while                      0.012174367904663086           0.009581327438354492           -27.063478239231593
 99 | gen/if8                        0.008812904357910156           0.00737762451171875            -19.454498448810757
100 | gen/parameterexpansion         0.0075032711029052734          0.0065996646881103516          -13.691701889382609
101 | gen/var1                       0.03267669677734375            0.013646364212036133           -139.45350035815994
102 | gen/var0                       0.009110450744628906           0.006860971450805664           -32.786600410049694
103 | gen/until                      0.006417751312255859           0.004626750946044922           -38.70967741935484
104 | gen/conditionals               0.008281469345092773           0.007395267486572266           -11.9833644980334
105 | gen/stringconcat               0.011516094207763672           0.007983922958374023           -44.24104876519246
106 | gen/if6                        0.013627767562866211           0.009176015853881836           -48.51508301504404
107 | gen/if5                        0.007302045822143555           0.0069348812103271484          -5.294461443256438
108 | gen/if4                        0.005690336227416992           0.005149364471435547           -10.50560237058987
109 | gen/if2                        0.03353404998779297            0.014903545379638672           -125.00719884818429
110 | gen/if1                        0.008652687072753906           0.006560087203979492           -31.89896420134472
111 | 
112 | 113 | # BUILD TESTS 114 | * wsl ./test.sh 115 | 116 | # TROUBLESHOOTING 117 | If something doesn't work, simplify your shell script and convert one at a time. 118 | Review missing functionality list. 119 | 120 | # MISSING FUNCTIONALITY 121 | ## HIGH PRIORITY 122 | * echo -e missing 123 | * checkroot.sh: while loop read from #9 file descriptor 124 | * checkroot.sh: exec descriptor handling 125 | * handle :exit 0 126 | * exec 0>&1 127 | * variable.sh: dropping TIMESTAMP variables 128 | * functions: parameter expansion inside awk string does not work 129 | * if [[ ( $username == "admin" && $password == "secret" ) ]] does not work 130 | * if [ -z ${VAR+x} ]; 131 | * dmesg -s 131072 > gen/dmesg doesn't work 132 | * echo {A..Z}{0..9} does not work 133 | * echo 1.{1..9} 134 | * str+=", " doesn't work 135 | * doesn't handle special characters well 136 | * has problems with cat << __EOF__ .. __EOF__ 137 | * regex string match in substring.sh does not work 138 | 139 | ## LOW PRIORITY 140 | * supports only 11 arguments 141 | * partial read support 142 | * echo -n is assumed to be the first three characters 143 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import sys 3 | import os 4 | import time 5 | import subprocess 6 | import argparse 7 | 8 | def get_params(): 9 | parser = argparse.ArgumentParser() 10 | parser.add_argument("-e", "--exectests", action='store_true', 11 | help="run build and exec tests only") 12 | parser.add_argument("-b", "--buildtests", action='store_true', 13 | help="run build tests only") 14 | parser.add_argument("-O0", "--reduceoptimization", action='store_true', 15 | help="reduce optimization level") 16 | parser.add_argument("-gp", "--enablegnuprofiling", action='store_true', 17 | help="enable profiling") 18 | parser.add_argument("-n", '--repeattests', type=int, 19 | help='repeat test') 20 | parser.add_argument("-t", '--tcmalloc', action='store_true', 21 | help='use tcmalloc library for heap operations') 22 | parser.add_argument("-c", '--clang', type=int, 23 | help='use clang compiler') 24 | parser.add_argument("-pr", '--enablegperfprofiling', action='store_true', 25 | help='use tcmalloc profiler for heap operations') 26 | parser.add_argument("-s", '--showsloweronly', action='store_true', 27 | help='show slower only') 28 | 29 | 30 | parser.add_argument('vars', nargs='*') 31 | params, unknown = parser.parse_known_args() 32 | return params, unknown 33 | 34 | params, unknown = get_params() 35 | vars = params.vars 36 | if unknown is not None: 37 | for u in unknown: 38 | vars.append(u) 39 | 40 | repeat=0 41 | gnuprofile=0 42 | clang=1 43 | tcmalloc=0 44 | gperfprofile=0 45 | runmeasuretestonly=0 46 | runbuildtestonly=0 47 | opt="-O3" 48 | showsloweronly=0 49 | 50 | if params.showsloweronly is not None: 51 | showsloweronly=params.showsloweronly 52 | 53 | if params.repeattests is not None: 54 | repeat=params.repeattests 55 | 56 | if params.tcmalloc is not None: 57 | tcmalloc=params.tcmalloc 58 | 59 | if params.clang is not None: 60 | clang=params.clang 61 | 62 | if params.enablegnuprofiling: 63 | gnuprofile=params.enablegnuprofiling 64 | 65 | if params.enablegperfprofiling: 66 | gperfprofile=params.enablegperfprofiling 67 | 68 | if params.reduceoptimization: 69 | opt="-O0 -g" 70 | 71 | if params.exectests: 72 | runmeasuretestonly=params.exectests 73 | 74 | if params.buildtests: 75 | runbuildtestonly=params.buildtests 76 | 77 | 78 | def execcommand(cmd): 79 | list_files = subprocess.run(cmd, stdout=subprocess.PIPE) 80 | return list_files.stdout.decode('utf-8'), list_files.returncode, list_files.stderr 81 | 82 | buildonly = [ 83 | "async.sh", 84 | "9.1.sh", 85 | "3.4.sh", 86 | # "banner.sh", 87 | "logic.sh", 88 | # Object.doubleQuoting 89 | # "populate-volatile.sh", 90 | # terminates in ConvertBash.convertStdRedirects 91 | # "checkroot.sh", 92 | "9.9.sh", 93 | # quote issue, 94 | # "9.8.sh", 95 | # quote problem, 96 | # "9.7.sh", 97 | # quote problem, 98 | # "9.6.sh", 99 | "9.5.sh", 100 | # crashes, 101 | # "9.4.sh", 102 | "9.3.sh", 103 | "9.2.sh", 104 | "8.5.sh", 105 | # parse problem, 106 | # Cannot parse arithmetic expression "36#zz": Unexpected character '#' (1: 107 | # "8.4.sh", 108 | "8.3.sh", 109 | # TypeError: Cannot read property 'start' of undefined 110 | # parse problem, 111 | # "8.2.sh", 112 | "8.1.sh", 113 | "7.7.sh", 114 | "7.6.sh", 115 | "7.5.sh", 116 | "7.4.sh", 117 | # divide by zero, 118 | # "7.3.sh", 119 | "7.2.sh", 120 | "7.1.sh", 121 | "6.2.sh", 122 | "6.1.sh", 123 | # Cannot read property 'singleQuoting' of undefined 124 | # parse problem, 125 | # "5.3.sh", 126 | # parse problem", 127 | # Cannot read property 'singleQuoting' of undefined 128 | # "5.2.sh", 129 | # quote issues, 130 | # "5.1.sh", 131 | "4.7.sh", 132 | "4.6.sh", 133 | "4.5.sh", 134 | "4.4.sh", 135 | "4.3.sh", 136 | "4.2.sh", 137 | "4.1.sh", 138 | "3.3.sh", 139 | "3.2.sh", 140 | "3.1.sh", 141 | "2.1.sh", 142 | "2.2.sh", 143 | "2.3.sh", 144 | "for3.sh", 145 | "urandom", 146 | "logic.sh", 147 | "read-only-rootfs-hook.sh", 148 | "hostname.sh", 149 | "if.sh", 150 | "functions", 151 | "dmesg.sh", 152 | "mountnfs.sh", 153 | "redirect.sh", 154 | "umountnfs.sh", 155 | "while0.sh", 156 | "read.sh", 157 | "variables.sh", 158 | "redirection.sh", 159 | "functions0.sh", 160 | "case.sh", 161 | "if7.sh", 162 | "for.sh", 163 | "alignment.sh", 164 | "bootmisc.sh", 165 | "checkfs.sh", 166 | "devpts.sh", 167 | "halt", 168 | "mountall.sh", 169 | "reboot", 170 | "rmnologin.sh", 171 | "save-rtc.sh", 172 | "sendsigs", 173 | "single", 174 | "sushell", 175 | "sysfs.sh", 176 | "umountfs" 177 | ] 178 | 179 | buildandexec = [ 180 | # "4.1.sh", 181 | # "3.3.sh", 182 | "exit.sh", 183 | "env3.sh", 184 | "env.sh", 185 | "pipeline0.sh", 186 | "emptyvar.sh", 187 | "for8.sh", 188 | "if10.sh", 189 | "local.sh", 190 | "default0.sh", 191 | "functions3.sh", 192 | "array0.sh", 193 | "array.sh", 194 | "for7.sh", 195 | "for5.sh", 196 | "for4.sh", 197 | "echo4.sh", 198 | "showsize.sh", 199 | "upper.sh", 200 | "echo3.sh", 201 | "functions2.sh", 202 | "lower0.sh", 203 | "upper0.sh", 204 | #"catinput.sh", 205 | #"substring.sh", 206 | "echo2.sh", 207 | "special.sh", 208 | # "regex.sh", 209 | # "split.sh", 210 | # "dirname.sh", 211 | # "replacement.sh", 212 | "functions1.sh", 213 | "arguments.sh 1 2 3", 214 | "arguments.sh 1", 215 | "arguments.sh", 216 | "for2.sh", 217 | "tildaexpansion.sh", 218 | "echo1.sh", 219 | "redirection0.sh", 220 | "while0.sh", 221 | "for0.sh", 222 | "braceexpansion.sh", 223 | "redirection.sh", 224 | "pipeline.sh", 225 | "hostname0.sh", 226 | "if9.sh", 227 | "redirect.sh", 228 | "while0.sh", 229 | "if3.sh", 230 | # "expansions.sh", 231 | # "for1.sh", 232 | "if0.sh", 233 | "case0.sh", 234 | "arithmetic.sh", 235 | "while.sh", 236 | "if8.sh", 237 | "parameterexpansion.sh", 238 | "var1.sh", 239 | "var0.sh", 240 | "until.sh", 241 | "conditionals.sh", 242 | "stringconcat.sh", 243 | "if6.sh", 244 | "if5.sh", 245 | "if4.sh", 246 | "if2.sh", 247 | "if1.sh" 248 | ] 249 | 250 | os.makedirs("gen", exist_ok=True) 251 | 252 | def convertlist(cmd): 253 | cmds=cmd.split() 254 | list = [] 255 | for a in cmds: 256 | list.append(a) 257 | return list 258 | 259 | def buildtest(testname=''): 260 | found = False 261 | for i in buildonly: 262 | if testname and testname[0]!='' and i!=testname[0]: 263 | continue 264 | found = True 265 | f=os.path.splitext(i)[0] 266 | cmd0="node app.js tests/" + i.split()[0] + " gen/" + f + ".cpp gen/" + f + ".log" 267 | list=convertlist(cmd0) 268 | out, result, err = execcommand(list) 269 | if result!=0: 270 | print(out) 271 | print(err) 272 | sys.exit(result) 273 | cmd1="gen/" + f + ".cpp -o gen/" + f + " " + opt + " -ffunction-sections -fdata-sections -Wl,--gc-sections -flto -lpcre -lpthread -lboost_system -lboost_filesystem -std=c++17" 274 | if clang: 275 | cmd1 = "clang++ " + cmd1 276 | else: 277 | cmd1 = "g++ " + cmd1 278 | 279 | if gnuprofile: 280 | cmd1 += " -pg" 281 | if tcmalloc: 282 | cmd1 += " -ltcmalloc " 283 | if gperfprofile: 284 | cmd1 += " -lprofiler " 285 | 286 | list=convertlist(cmd1) 287 | out0, result, err = execcommand(list) 288 | if result!=0: 289 | sys.exit(result) 290 | print("%-30s" % (f)) 291 | 292 | if found == False: 293 | print('test not found') 294 | sys.exit() 295 | 296 | def buildtestone(i): 297 | f=os.path.splitext(i)[0] 298 | cmd0="node app.js tests/" + i.split()[0] + " gen/" + f + ".cpp gen/" + f + ".log" 299 | list=convertlist(cmd0) 300 | out, result, err = execcommand(list) 301 | if result!=0: 302 | sys.exit(result) 303 | cmd1="gen/" + f + ".cpp -o gen/" + f + " " + opt + " -ffunction-sections -fdata-sections -Wl,--gc-sections -flto -lpcre -lpthread -lboost_system -lboost_filesystem -std=c++17" 304 | if clang: 305 | cmd1 = "clang++ " + cmd1 306 | else: 307 | cmd1 = "g++ " + cmd1 308 | if gnuprofile: 309 | cmd1 += " -pg" 310 | if tcmalloc: 311 | cmd1 += " -ltcmalloc " 312 | if gperfprofile: 313 | cmd1 += " -lprofiler " 314 | 315 | list=convertlist(cmd1) 316 | out0, result, err = execcommand(list) 317 | if result!=0: 318 | sys.exit(result) 319 | 320 | def exectestone(i,printresult = True, showsloweronly = False): 321 | args=i.split() 322 | args.pop(0) 323 | l="tests/{}".format(i) 324 | if args: 325 | list = [] 326 | list.append("bash") 327 | list.append(l.split()[0]) 328 | for a in args: 329 | list.append(a) 330 | start_time = time.time() 331 | out0, result, err = execcommand(list) 332 | else: 333 | start_time = time.time() 334 | out0, result, err = execcommand(["bash", l]) 335 | elapsed_time0 = time.time() - start_time 336 | 337 | if args: 338 | list = [] 339 | list.append("gen/{}".format(os.path.splitext(i)[0])) 340 | for a in args: 341 | list.append(a) 342 | start_time = time.time() 343 | out1, result, err = execcommand(list) 344 | else: 345 | l="gen/{}".format(os.path.splitext(i)[0]) 346 | start_time = time.time() 347 | out1, result, err = execcommand([l]) 348 | 349 | elapsed_time1 = time.time() - start_time 350 | if printresult and ((showsloweronly == False) or (elapsed_time1 > elapsed_time0)): 351 | print("%-30s %-30s %-30s %-30s" % (l, elapsed_time0, elapsed_time1, ((elapsed_time1 - elapsed_time0) * 100) / elapsed_time1)) 352 | if out0 != out1: 353 | text_file = open("out0.txt", "wt") 354 | text_file.write(out0) 355 | text_file.close() 356 | text_file = open("out1.txt", "wt") 357 | text_file.write(out1) 358 | text_file.close() 359 | print("{} failed".format(l)) 360 | sys.exit(1) 361 | return (l, elapsed_time0, elapsed_time1, ((elapsed_time1 - elapsed_time0) * 100) / elapsed_time1) 362 | 363 | def buildandexectest(repeat, testname='', showsloweronly=False): 364 | found = False 365 | for i in buildandexec: 366 | if testname and testname[0]!='' and i!=testname[0]: 367 | continue 368 | found = True 369 | if repeat: 370 | average0=0 371 | average1=0 372 | average2=0 373 | r=repeat 374 | name="" 375 | buildtestone(i) 376 | while r > 0: 377 | [name, elapsed_time0, elapsed_time1, delta,] = exectestone(i, False, showsloweronly) 378 | average0 = average0 + elapsed_time0 379 | average1 = average1 + elapsed_time1 380 | average2 = average2 + delta 381 | r=r-1 382 | #print("==============================================================================================================") 383 | if (showsloweronly == False) or (average1 > average0): 384 | print("%-30s %-30s %-30s %-30s" % ("average:" + name, average0/repeat, average1/repeat, average2/repeat)) 385 | else: 386 | buildtestone(i) 387 | exectestone(i) 388 | if found == False: 389 | print('test not found') 390 | sys.exit() 391 | 392 | if runbuildtestonly: 393 | buildtest(vars) 394 | sys.exit() 395 | 396 | if runmeasuretestonly: 397 | buildandexectest(repeat, vars, showsloweronly) 398 | sys.exit() 399 | 400 | buildtest() 401 | buildandexectest(repeat, vars, showsloweronly) 402 | --------------------------------------------------------------------------------