├── .gitignore ├── LICENSE ├── README.md ├── bootstrap.sh ├── compile.sh ├── contrib ├── elap.bash-v2 ├── profile.py ├── profiler.bash ├── shc-3.8.9 │ ├── CHANGES │ ├── Copying │ ├── Makefile │ ├── match │ ├── match.x │ ├── match.x.c │ ├── pru.sh │ ├── shc │ ├── shc-3.8.9.c │ ├── shc.1 │ ├── shc.README │ ├── shc.c │ ├── shc.html │ ├── test.bash │ ├── test.csh │ └── test.ksh └── shellscriptloader-0.1.1 │ ├── changelog.txt │ ├── compiler │ ├── compiler-20141212.gawk │ ├── loader.bash │ ├── loader.ksh │ ├── loader.sh │ ├── loader.txt │ ├── loader.zsh │ ├── module.txt │ └── version.txt ├── packages ├── nvidia │ ├── .gitignore │ ├── Makefile │ ├── gpu-change │ ├── gpu-run │ ├── gpu-state │ ├── gpu-tailstats │ └── gpu-testglx ├── sonybravia │ ├── .gitignore │ ├── Makefile │ ├── commands.json │ ├── sonybravia-ctl │ └── sonybravia-remote ├── themer │ ├── .gitignore │ ├── Makefile │ ├── _themer │ ├── theme-activate │ └── theme-edit └── x11 │ ├── xmatch │ ├── xwid │ ├── xwincenter │ ├── xwindowname │ ├── xwinprocess │ └── xwmstrut ├── standalone ├── encryptandsign ├── lpassfind ├── time_exec └── timeout_prompt.sh ├── tpl.sh └── utils ├── _.sh ├── algo.sh ├── alsa.sh ├── ansi.sh ├── atexit.sh ├── cli.sh ├── cli2.sh ├── color.sh ├── json.sh ├── keycode.sh ├── log.sh ├── log ├── _tests.sh ├── banner.sh ├── defer.sh ├── format │ ├── blocks.sh │ ├── icons.sh │ ├── plain.sh │ ├── slim.sh │ └── tags.sh └── log.sh ├── math.sh ├── notification.sh ├── pipe.sh ├── polybar.sh ├── proc.sh ├── runit.sh ├── spinner.sh ├── str.sh ├── testkit.sh ├── tests.sh ├── tests ├── algo.sh ├── ansi.sh ├── color.sh ├── json.sh ├── math.sh ├── pipe.sh ├── proc.sh ├── spinner.sh └── str.sh └── x11.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.git 2 | *.bak 3 | *.old 4 | *.tmp 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Michael Carlberg 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##### src // sh 2 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source shellscriptloader-0.1.1.sh || exit 1 3 | 4 | loader_addpath "$(dirname "${BASH_SOURCE[0]}")" 5 | 6 | function bootstrap::finish { 7 | loader_finish 8 | } 9 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # TODO: support nested [post-pass:] blocks 3 | 4 | function main 5 | { 6 | exec >&2 7 | 8 | if [[ $# -lt 2 ]]; then 9 | echo "Usage: $0 [compiler_flags...]"; exit 1 10 | fi 11 | 12 | local compiler="${SHELLSCRIPTLOADER_COMPILER:-$(dirname "$0")/contrib/shellscriptloader-0.1.1/compiler}" 13 | 14 | if ! [[ -e "$compiler" ]]; then 15 | echo "error: Compiler script \"$compiler\" does not exist. Specify path using SHELLSCRIPTLOADER_COMPILER"; exit 2 16 | fi 17 | 18 | local input="$1"; shift 19 | local output="$1"; shift 20 | local flags="" 21 | 22 | while [[ $# -gt 0 ]]; do 23 | flags="$flags $1"; shift 24 | done 25 | 26 | cp "$input" "$output" 27 | 28 | echo "pre-pass: replace alias fn (bootstrap::finish -> loader_finish)" 29 | sed -i 's/bootstrap::finish/loader_finish/' "$output" 30 | 31 | local execline="gawk -f $compiler --$flags -o ${output}.out $output" 32 | echo "$execline" 33 | eval "$execline" 34 | 35 | mv "${output}.out" "$output" 36 | 37 | if [[ $? -eq 0 ]]; then 38 | chmod +x "$output" 39 | fi 40 | 41 | IFS=$'\n' 42 | 43 | local -i pass=0 44 | 45 | # remove unused function definitions 46 | while (( pass++ <= 5 )) 47 | do 48 | local fn_name unused_fn inside_fn 49 | local -i line_no=0 unused_line_start=0 50 | 51 | cp "$output" "${output}.min" 52 | 53 | # shellcheck disable=2094 54 | while read -r line; do 55 | let line_no++ 56 | 57 | # check for function body close tag 58 | if $inside_fn; then 59 | if [[ "$line" == "}" ]]; then 60 | inside_fn='false' 61 | 62 | # remove function body 63 | if [[ "$unused_fn" ]]; then 64 | echo "post-pass #${pass}: Removing unused function '$unused_fn' (lines ${unused_line_start}-${line_no})" 65 | sed -i "${unused_line_start},${line_no}s/.*//" "${output}.min" 66 | unset unused_fn 67 | fi 68 | fi 69 | 70 | continue 71 | fi 72 | 73 | # check for function body open statement 74 | fn_name=$(sed -nr 's/^function ([^ ]+) ?\{?$/\1/p' <<< "$line") 75 | 76 | if ! [[ "$fn_name" ]]; then 77 | continue 78 | fi 79 | 80 | inside_fn='true' 81 | 82 | # check for any occurrences of fn_name other than the definition 83 | if ! grep -v "function $fn_name" "${output}.min" | egrep -q "( |trap .*|\(|\`|\||^)${fn_name}( |\)|\`|'|\||;|>|$)"; then 84 | unused_fn="$fn_name" 85 | unused_line_start=$line_no 86 | fi 87 | done < "$output" 88 | 89 | mv "${output}.min" "$output" 90 | done 91 | 92 | cp "$output" "${output}.min" 93 | 94 | # remove code blocks that depends on unused functions 95 | # test '[post-pass:require-fn=log::defer]' 96 | # .... 97 | # test '[/post-pass]' 98 | local -i line_no=0 block_start=0 99 | local require_fn 100 | 101 | while read -r line; do 102 | let line_no++ 103 | 104 | if [[ "$line" == "test '[/post-pass:require-fn]'" ]]; then 105 | if [[ $block_start -gt 0 ]]; then 106 | echo "post-pass: Removing code block depending on '${require_fn}' (lines ${block_start}-${line_no})" 107 | sed -i "${block_start},${line_no}s/.*//" "${output}.min" 108 | let block_start=0 109 | else 110 | sed -i "${line_no}s/.*//" "${output}.min" 111 | fi 112 | continue 113 | elif [[ $block_start -gt 0 ]]; then 114 | continue 115 | fi 116 | 117 | require_fn=$(sed -nr 's/test .\[post-pass:require-fn=(.*)\]/\1/p' <<< "$line" | tr -d "'") 118 | 119 | if ! [[ "$require_fn" ]]; then 120 | continue 121 | fi 122 | 123 | # look for the function body 124 | if egrep -q "function[ ]*$require_fn" "${output}.min"; then 125 | sed -i "${line_no}s/.*//" "${output}.min" 126 | else 127 | let block_start=line_no 128 | fi 129 | done < "$output" 130 | 131 | mv "${output}.min" "$output" 132 | 133 | # Strip bootstrap 134 | sed -r -i '/source[ ]+bootstrap.sh/d' "$output" 135 | 136 | # Strip consecutive blank lines 137 | # sed -i 'N; /^\n$/d; P; D' "$output" 138 | 139 | # Strip blank lines 140 | sed -i '/^$/d' "$output" 141 | } 142 | 143 | main "$@" 144 | -------------------------------------------------------------------------------- /contrib/elap.bash-v2: -------------------------------------------------------------------------------- 1 | # 2 | # Elap bash source file Version 2 3 | # Based on /proc/timer_list only 4 | # 5 | # Usage: 6 | # source elap.bash [init|trap|trap2] 7 | # 8 | # Bunch of functions without test for ensuring minimum time consumption 9 | # 10 | # 11 | 12 | # Useable functions 13 | elap() { elapGetNow;elapCalc;elapShow "$@";elapCnt;} 14 | elapTotal() { elapGetNow;elapCalc2;elapShowTotal "$@";} 15 | elapBoth() { elapGetNow;elapCalc;elapCalc2;elapShowBoth "$@";elapCnt;} 16 | elapReset() { elapGetNow;elapCnt;} 17 | elapResetTotal(){ elapGetNow;elapCntTotal;} 18 | elapResetBoth() { elapGetNow;elapCntBoth;} 19 | 20 | # Semi internal functions 21 | elapShow() { echo -e "$_elap $@";} 22 | elapShowTotal() { echo -e "$_elap2 $@";} 23 | elapShowBoth() { echo -e "$_elap $_elap2 $@";} 24 | 25 | # Internal functions 26 | elapCnt() { _eLast=$_eNow ;} 27 | elapCntTotal() { _eLast2=$_eNow;} 28 | elapCntBoth() { _eLast=$_eNow ; _eLast2=$_eNow;} 29 | elapGetNow() { 30 | read -dk -a_eNow $_shLogFile 24 | rm $_shLogFile 25 | exec 28$_shTimeFile 28 | rm $_shTimeFile 29 | exec 27 >( 31 | tee /dev/fd/29 | 32 | sed -u 's/.*/now/' | 33 | date -f - +%s%N >&30 34 | ) 35 | trap "_printLog $*" 0 1 2 3 6 9 15 36 | BASH_XTRACEFD=31 37 | set -x 38 | } 39 | _printLog() { 40 | set +x 41 | local _shLast= _shTim= _shCrt= _shTot=0 _shC=0000000000 _shT=0000000000 \ 42 | _shCnt=100 _shFmtStr= _shLogLine= _shNumLen=9 _shFracLen=5 43 | while getopts "hw:p:" _shCrt;do case $_shCrt in 44 | w ) _shCnt=$[10*OPTARG] ;; 45 | p ) _shFracLen=$[OPTARG];; 46 | * ) printf >&2 "Error: %s: Argument '%s' unknown.\n" $0 $_shCrt;; 47 | esac; done; 48 | # Delay upto 10 second if there are unfinished childs 49 | while [ $(jobs -p|wc -l) -gt 0 ] && ((_shCnt--)) ;do 50 | sleep .1 51 | done 52 | # Print unfinished jobs if any 53 | jobs 54 | # Close trace FD 55 | exec 31>&- 56 | sync 57 | # Whipe 1st null line, take base time. 58 | read -u 27 _shLast 59 | printf -v _shNumLen "%(%s)T-%s\n" -1 ${_shLast:0:${#_shLast}-9} 60 | _shNumLen=$[_shNumLen] 61 | _shNumLen=$[1+${#_shNumLen}+_shFracLen] 62 | printf -v _shFmtStr "%%%d.%df %%%d.%df %%s\\n" \ 63 | $_shNumLen $_shFracLen $_shNumLen $_shFracLen 64 | while read -u 27 _shTim ;do 65 | read -u 28 _shLogLine 66 | _shCrt=$[ _shTim-_shLast ] 67 | ((_shTot+=_shCrt)) 68 | _shC=0000000000$_shCrt _shT=0000000000$_shTot 69 | printf "$_shFmtStr" ${_shC:0:${#_shC}-9}.${_shC:${#_shC}-9} \ 70 | ${_shT:0:${#_shT}-9}.${_shT:${#_shT}-9} "$_shLogLine" 71 | ((_shLast=_shTim)) 72 | done 73 | printf "$_shFmtStr" ${_shT:0:${#_shT}-9}.${_shT:${#_shT}-9}{,} Total 74 | exec 27>&- 28>&- 29>&- 30>&- 31>&- 75 | exit 76 | } 77 | _shTrace $@ 78 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/CHANGES: -------------------------------------------------------------------------------- 1 | CHANGES 2 | 3 | 3.8.9 Wed Apr 25 09:24:25 CEST 2012 4 | 5 | Thanks to Giacomo Picconi for: 6 | - Fixing a long standing bug making the source not hidden. 7 | 8 | 9 | 10 | 3.8.8 Mon Nov 28 11:26:25 CEST 2012 11 | 12 | "me". 13 | 14 | 15 | 16 | 3.8.7 Wed Feb 10 20:40:37 CET 2010 17 | 18 | - Bug on 64bit systems with expiration dates. 19 | 20 | 21 | 22 | 3.8.6 Fri Jul 7 15:54:39 CEST 2006 23 | 24 | Thanks to George Danchev for: 25 | - License clarification about the rc4 implementation. 26 | 27 | 28 | 29 | 3.8.5 Fri Oct 21 13:11:36 CEST 2005 30 | 31 | Thanks to Jukka A. Ukkonen for: 32 | - Fixed untraceable() problems on FreeBSD. 33 | 34 | 35 | 36 | 3.8.4 Tue Oct 4 16:52:15 CEST 2005 37 | 38 | Thanks to Ron McOuat for: 39 | - Fixed sma11 -d option bug. 40 | 41 | 42 | 43 | 3.8.3 Tue Jun 28 21:29:06 CEST 2005 44 | 45 | Thanks to Jacek Kalinski for: 46 | - Fixed bug: "vfork" fails on multiprocessor systems. 47 | 48 | 49 | 50 | 3.8.2 Thu Jun 16 17:15:59 CEST 2005 51 | 52 | Thanks to Arjen Visser for: 53 | - Fixed bug: "rlax" used after encryption. 54 | 55 | Thanks to Nalneesh Gaur for: 56 | - Read permision of the script.x exposes it to disassembling. 57 | - Group and others read permision is now removed by default. 58 | 59 | 60 | 61 | 3.8 Thu Nov 4 20:33:52 CET 2004 62 | 63 | Fixed incorrect implementation on rc4. 64 | Hidden all the binary executable symbols but one. 65 | Expiration date and most strings are encrypted too. 66 | All the encrypted payload is now randomized. 67 | 68 | 69 | 70 | 3.7 Wed Jun 18 16:32:26 CEST 2003 71 | 72 | Thanks to Philipp Koller for: 73 | - Removed all strings in the compiled script. 74 | - Improved program output and error messages. 75 | - The -m option allows to define the *complete* expiration message. 76 | - Updated manpage shc.1. 77 | 78 | Thanks to Bryan for: 79 | - Fix wrong $0 on ksh. 80 | 81 | 82 | 83 | 3.6 Fri Feb 21 09:40:32 CET 2003 84 | 85 | Two new options: 86 | -D switch on Debug exec calls. 87 | -T switch off unTraceable. 88 | 89 | Bash does not need -- after -c. 90 | 91 | 92 | 93 | 3.5 Mon Jan 20 19:08:43 CET 2003 94 | 95 | Rewrite of large strings to silence the ISO C89 compiler 96 | warnings about strings larger than 509 characters. 97 | 98 | 99 | 100 | 3.4 Tue Apr 16 17:43:12 CEST 2002 101 | 102 | Remove "bad alignment" problem on AIX and other systems. 103 | Where exists, use /proc//as in untraceable. 104 | 105 | 106 | 107 | 3.3 Thu Jan 24 21:27:07 CET 2002 108 | 109 | Prevent to ptrace the process. 110 | 111 | 112 | 113 | 3.2 Tue Mar 9 19:03:54 CET 1999 114 | 115 | Find ancient pclose that must be fclose. 116 | 117 | 118 | 119 | 3.1 Tue Feb 16 21:36:59 CET 1999 120 | 121 | Fixed a misbehavior on scripts with a in-frist-line option 122 | equal to "end of options" (i.e. #!/bin/sh -- ) 123 | (Thanks to Bernard Blundell ) 124 | 125 | Stupid GCC "warning: return type of `main' is not `int'" removed. 126 | 127 | 128 | 129 | 3.0 Tue Oct 14 14:20:52 MET DST 1997 130 | 131 | Added a new option "-r" to force a relaxed security and 132 | so make a redistributable binary. 133 | 134 | Modified expiration day format. Now is dd/mm/yyyy. 135 | 136 | 137 | 138 | 3.0b3 Fri Jun 6 22:09:05 WET DST 1997 139 | 140 | Yet other few bugs fixed. 141 | Output format simplified. 142 | -pedantic compilation. 143 | 144 | 145 | 146 | 3.0b2 Tue Jun 3 17:51:51 GMT 1997 147 | 148 | Some explicit type conversions removed. 149 | 150 | Fixed the bug "END_OF_FILE" when compiling the generated code. 151 | A flush is needed before a pclose. 152 | 153 | st_blksize and st_blocks struct stat fields does not exist on 154 | SCO, both not used now. 155 | 156 | 157 | 158 | 3.0b1 Wed Feb 26 14:27:22 WET 1997 159 | 160 | The main difference with 2.4 is that in it the script was 161 | compressed an then shuffle around, now int 3.0 the script is encripted 162 | with an inline code, so not needend any external comand to work, and been 163 | faster at startup. Other related adventage is that the only information 164 | not encripted in .x.c is an stamp, expiration date and provider email 165 | address. 166 | 167 | Something equivalent to cheksums have been used to enforced at 168 | execution that the executing shell has not been modified from the time 169 | the script was compiled. If anybody tries to change the excuting shell, 170 | .x will refuse to execute. 171 | 172 | The generated .x.c source code is now readable. 173 | 174 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/Copying: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 675 Mass Ave, Cambridge, MA 02139, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | Appendix: How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 19yy 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) 19yy name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Library General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaagr/shellscripts/dc2dd7addeb2e1bb794d9c459adffaafea757783/contrib/shc-3.8.9/Makefile -------------------------------------------------------------------------------- /contrib/shc-3.8.9/match: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # File search script by 4 | # Usage: match [Filename] 5 | # 6 | IFS=":$IFS" 7 | 8 | for substring in $@ 9 | do 10 | for path in $PATH 11 | do 12 | for command in $path/*$substring* 13 | do 14 | if [ -f $command ] 15 | then 16 | echo $command 17 | fi 18 | done 19 | done 20 | done 21 | 22 | # Added 23 | echo "[$$] PAUSED... Hit return!" 24 | read DUMMY 25 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/match.x: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaagr/shellscripts/dc2dd7addeb2e1bb794d9c459adffaafea757783/contrib/shc-3.8.9/match.x -------------------------------------------------------------------------------- /contrib/shc-3.8.9/match.x.c: -------------------------------------------------------------------------------- 1 | #if 0 2 | shc Version 3.8.9, Generic Script Compiler 3 | Copyright (c) 1994-2012 Francisco Rosales 4 | 5 | ./shc -v -f match 6 | #endif 7 | 8 | static char data [] = 9 | #define msg1_z 42 10 | #define msg1 ((&data[0])) 11 | "\212\011\245\131\234\115\231\032\012\201\215\273\250\045\317\260" 12 | "\301\176\266\060\254\302\031\145\223\037\310\021\224\113\152\167" 13 | "\002\324\254\254\352\364\350\263\145\250" 14 | #define chk2_z 19 15 | #define chk2 ((&data[44])) 16 | "\115\056\322\327\210\042\264\135\016\136\117\363\362\156\042\204" 17 | "\044\363\305\032\213\026\010\002" 18 | #define chk1_z 22 19 | #define chk1 ((&data[68])) 20 | "\236\240\114\301\156\001\335\145\217\063\034\270\346\227\035\331" 21 | "\237\261\002\000\020\075\127\044\027\270\102\074" 22 | #define shll_z 8 23 | #define shll ((&data[95])) 24 | "\077\301\340\110\304\244\305\042\102\363" 25 | #define lsto_z 1 26 | #define lsto ((&data[104])) 27 | "\352" 28 | #define pswd_z 256 29 | #define pswd ((&data[140])) 30 | "\016\222\245\010\371\132\126\050\161\136\053\001\301\337\240\142" 31 | "\366\130\245\063\221\027\260\321\012\047\354\116\034\167\363\053" 32 | "\012\231\063\160\105\153\335\172\241\104\353\347\233\315\246\363" 33 | "\170\254\072\334\210\225\074\240\360\076\227\236\137\245\010\071" 34 | "\164\213\251\271\366\207\064\230\314\037\200\147\354\047\133\145" 35 | "\323\225\101\133\053\176\374\034\275\223\272\034\070\302\126\255" 36 | "\115\377\146\104\207\233\335\123\273\135\273\247\204\026\015\127" 37 | "\254\116\263\330\315\257\364\212\103\256\247\173\160\375\050\276" 38 | "\375\217\002\204\052\337\330\345\075\224\215\301\253\233\031\127" 39 | "\352\314\060\267\174\044\102\277\322\351\073\103\346\144\001\343" 40 | "\364\004\150\037\343\101\005\041\325\223\342\200\056\374\330\030" 41 | "\311\010\320\105\054\022\005\377\373\101\102\342\246\103\306\233" 42 | "\107\056\272\053\157\277\114\105\123\057\305\201\053\235\232\364" 43 | "\245\152\072\322\174\100\321\167\202\023\132\051\127\040\304\236" 44 | "\116\176\312\276\076\027\003\221\106\311\023\161\146\255\146\014" 45 | "\027\241\336\224\341\257\014\144\303\146\215\032\206\121\271\325" 46 | "\320\203\223\016\233\227\240\341\140\264\123\307\141\272\323\171" 47 | "\133\262\015\075\142\032\241\045\200\057\100\006\200\371\333\121" 48 | "\175\157\140\003\363\211\054\145\350\127\147\252\067\007\014\056" 49 | "\140\262\142\361\311\023\303\324\073\257\043\130\047\027\203\061" 50 | "\260\266\065\244\100\142\011\051\272\160\323\361" 51 | #define tst1_z 22 52 | #define tst1 ((&data[442])) 53 | "\330\222\203\312\134\341\077\324\006\012\202\034\221\201\112\264" 54 | "\266\355\263\370\044\332\136\103\307\376\004" 55 | #define msg2_z 19 56 | #define msg2 ((&data[466])) 57 | "\322\075\202\343\054\372\221\102\057\352\013\264\202\237\143\277" 58 | "\300\300\253\157\106" 59 | #define inlo_z 3 60 | #define inlo ((&data[485])) 61 | "\033\112\021" 62 | #define rlax_z 1 63 | #define rlax ((&data[488])) 64 | "\217" 65 | #define date_z 1 66 | #define date ((&data[489])) 67 | "\065" 68 | #define opts_z 1 69 | #define opts ((&data[490])) 70 | "\374" 71 | #define text_z 337 72 | #define text ((&data[559])) 73 | "\072\241\332\263\202\373\213\024\176\125\160\025\343\241\347\040" 74 | "\366\022\205\142\277\033\176\044\350\076\312\026\010\230\377\103" 75 | "\072\332\366\274\326\201\321\124\327\102\152\272\344\122\333\332" 76 | "\144\140\074\044\174\272\110\144\371\023\173\001\254\173\104\346" 77 | "\125\072\243\053\044\153\234\007\147\332\330\051\215\061\366\300" 78 | "\313\303\214\012\015\245\054\033\340\102\372\263\110\226\246\334" 79 | "\322\313\251\036\347\124\313\113\031\002\103\106\100\077\132\121" 80 | "\131\210\044\211\241\104\105\245\345\360\303\347\303\236\152\171" 81 | "\221\014\037\340\303\076\227\261\240\375\042\337\237\212\253\106" 82 | "\137\144\323\077\062\244\221\333\203\262\106\176\270\367\045\253" 83 | "\365\175\000\260\223\033\215\100\362\224\150\264\020\047\221\003" 84 | "\315\266\073\352\311\350\155\061\134\077\064\373\271\376\276\104" 85 | "\133\337\365\261\366\150\011\100\063\351\021\257\160\164\056\074" 86 | "\207\067\005\334\360\313\211\106\013\257\150\057\150\011\147\100" 87 | "\376\362\203\204\105\021\213\375\063\127\266\024\120\064\365\255" 88 | "\013\205\267\331\114\106\062\350\301\305\076\047\161\353\301\207" 89 | "\206\152\016\100\155\215\126\114\036\147\350\115\151\052\327\160" 90 | "\146\304\234\331\244\356\004\336\203\363\354\156\020\050\135\210" 91 | "\154\034\056\023\131\102\161\201\134\172\172\333\204\047\175\275" 92 | "\170\253\020\142\101\337\367\176\123\363\246\370\061\117\306\223" 93 | "\270\050\152\041\103\327\076\240\122\146\170\152\371\112\074\345" 94 | "\243\021\004\341\154\356\302\344\177\260\207\376\176\360\201\376" 95 | "\042\070\134\364\165\255\270\110\111\326\115\154\363\223\352\256" 96 | "\254\133\357\307\001\120\047\350\265\277\170\140\217\005\035\231" 97 | "\377\377\104\163\304\200\264\053\367\215\023\266\017\372\236\371" 98 | "\015\301\375\001\226\274\165\200\223\267\353\116\233\075\051\166" 99 | "\241\212\263\305\006\156\016\153\147\041\346\151\316\142\256\264" 100 | "\270\351\130\343\245\315\144\071\205\117\207\040\215\261\227\056" 101 | "\073\112\364\102\270\003\255\040\045\224\211\363\366\067\250\256" 102 | "\041\001\222\306\316\367\377\124\107\207\165\324\070\014\003\164" 103 | "\127\367" 104 | #define tst2_z 19 105 | #define tst2 ((&data[973])) 106 | "\352\344\255\141\115\135\000\241\326\120\110\366\250\274\126\033" 107 | "\236\214\370\143\060\040\370" 108 | #define xecc_z 15 109 | #define xecc ((&data[996])) 110 | "\053\312\230\041\065\361\157\025\375\357\060\261\353\151\307\362" 111 | "\274\236"/* End of data[] */; 112 | #define hide_z 4096 113 | #define DEBUGEXEC 0 /* Define as 1 to debug execvp calls */ 114 | #define TRACEABLE 0 /* Define as 1 to enable ptrace the executable */ 115 | 116 | /* rtc.c */ 117 | 118 | #include 119 | #include 120 | 121 | #include 122 | #include 123 | #include 124 | #include 125 | #include 126 | #include 127 | 128 | /* 'Alleged RC4' */ 129 | 130 | static unsigned char stte[256], indx, jndx, kndx; 131 | 132 | /* 133 | * Reset arc4 stte. 134 | */ 135 | void stte_0(void) 136 | { 137 | indx = jndx = kndx = 0; 138 | do { 139 | stte[indx] = indx; 140 | } while (++indx); 141 | } 142 | 143 | /* 144 | * Set key. Can be used more than once. 145 | */ 146 | void key(void * str, int len) 147 | { 148 | unsigned char tmp, * ptr = (unsigned char *)str; 149 | while (len > 0) { 150 | do { 151 | tmp = stte[indx]; 152 | kndx += tmp; 153 | kndx += ptr[(int)indx % len]; 154 | stte[indx] = stte[kndx]; 155 | stte[kndx] = tmp; 156 | } while (++indx); 157 | ptr += 256; 158 | len -= 256; 159 | } 160 | } 161 | 162 | /* 163 | * Crypt data. 164 | */ 165 | void arc4(void * str, int len) 166 | { 167 | unsigned char tmp, * ptr = (unsigned char *)str; 168 | while (len > 0) { 169 | indx++; 170 | tmp = stte[indx]; 171 | jndx += tmp; 172 | stte[indx] = stte[jndx]; 173 | stte[jndx] = tmp; 174 | tmp += stte[indx]; 175 | *ptr ^= stte[tmp]; 176 | ptr++; 177 | len--; 178 | } 179 | } 180 | 181 | /* End of ARC4 */ 182 | 183 | /* 184 | * Key with file invariants. 185 | */ 186 | int key_with_file(char * file) 187 | { 188 | struct stat statf[1]; 189 | struct stat control[1]; 190 | 191 | if (stat(file, statf) < 0) 192 | return -1; 193 | 194 | /* Turn on stable fields */ 195 | memset(control, 0, sizeof(control)); 196 | control->st_ino = statf->st_ino; 197 | control->st_dev = statf->st_dev; 198 | control->st_rdev = statf->st_rdev; 199 | control->st_uid = statf->st_uid; 200 | control->st_gid = statf->st_gid; 201 | control->st_size = statf->st_size; 202 | control->st_mtime = statf->st_mtime; 203 | control->st_ctime = statf->st_ctime; 204 | key(control, sizeof(control)); 205 | return 0; 206 | } 207 | 208 | #if DEBUGEXEC 209 | void debugexec(char * sh11, int argc, char ** argv) 210 | { 211 | int i; 212 | fprintf(stderr, "shll=%s\n", sh11 ? sh11 : ""); 213 | fprintf(stderr, "argc=%d\n", argc); 214 | if (!argv) { 215 | fprintf(stderr, "argv=\n"); 216 | } else { 217 | for (i = 0; i <= argc ; i++) 218 | fprintf(stderr, "argv[%d]=%.60s\n", i, argv[i] ? argv[i] : ""); 219 | } 220 | } 221 | #endif /* DEBUGEXEC */ 222 | 223 | void rmarg(char ** argv, char * arg) 224 | { 225 | for (; argv && *argv && *argv != arg; argv++); 226 | for (; argv && *argv; argv++) 227 | *argv = argv[1]; 228 | } 229 | 230 | int chkenv(int argc) 231 | { 232 | char buff[512]; 233 | unsigned long mask, m; 234 | int l, a, c; 235 | char * string; 236 | extern char ** environ; 237 | 238 | mask = (unsigned long)&chkenv; 239 | mask ^= (unsigned long)getpid() * ~mask; 240 | sprintf(buff, "x%lx", mask); 241 | string = getenv(buff); 242 | #if DEBUGEXEC 243 | fprintf(stderr, "getenv(%s)=%s\n", buff, string ? string : ""); 244 | #endif 245 | l = strlen(buff); 246 | if (!string) { 247 | /* 1st */ 248 | sprintf(&buff[l], "=%lu %d", mask, argc); 249 | putenv(strdup(buff)); 250 | return 0; 251 | } 252 | c = sscanf(string, "%lu %d%c", &m, &a, buff); 253 | if (c == 2 && m == mask) { 254 | /* 3rd */ 255 | rmarg(environ, &string[-l - 1]); 256 | return 1 + (argc - a); 257 | } 258 | return -1; 259 | } 260 | 261 | #if !TRACEABLE 262 | 263 | #define _LINUX_SOURCE_COMPAT 264 | #include 265 | #include 266 | #include 267 | #include 268 | #include 269 | #include 270 | #include 271 | 272 | #if !defined(PTRACE_ATTACH) && defined(PT_ATTACH) 273 | # define PTRACE_ATTACH PT_ATTACH 274 | #endif 275 | void untraceable(char * argv0) 276 | { 277 | char proc[80]; 278 | int pid, mine; 279 | 280 | switch(pid = fork()) { 281 | case 0: 282 | pid = getppid(); 283 | /* For problematic SunOS ptrace */ 284 | #if defined(__FreeBSD__) 285 | sprintf(proc, "/proc/%d/mem", (int)pid); 286 | #else 287 | sprintf(proc, "/proc/%d/as", (int)pid); 288 | #endif 289 | close(0); 290 | mine = !open(proc, O_RDWR|O_EXCL); 291 | if (!mine && errno != EBUSY) 292 | mine = !ptrace(PTRACE_ATTACH, pid, 0, 0); 293 | if (mine) { 294 | kill(pid, SIGCONT); 295 | } else { 296 | perror(argv0); 297 | kill(pid, SIGKILL); 298 | } 299 | _exit(mine); 300 | case -1: 301 | break; 302 | default: 303 | if (pid == waitpid(pid, 0, 0)) 304 | return; 305 | } 306 | perror(argv0); 307 | _exit(1); 308 | } 309 | #endif /* !TRACEABLE */ 310 | 311 | char * xsh(int argc, char ** argv) 312 | { 313 | char * scrpt; 314 | int ret, i, j; 315 | char ** varg; 316 | char * me = getenv("_"); 317 | if (me == NULL) { me = argv[0]; } 318 | 319 | stte_0(); 320 | key(pswd, pswd_z); 321 | arc4(msg1, msg1_z); 322 | arc4(date, date_z); 323 | if (date[0] && (atoll(date) 1) ? ret : 0; /* Args numbering correction */ 378 | while (i < argc) 379 | varg[j++] = argv[i++]; /* Main run-time arguments */ 380 | varg[j] = 0; /* NULL terminated array */ 381 | #if DEBUGEXEC 382 | debugexec(shll, j, varg); 383 | #endif 384 | execvp(shll, varg); 385 | return shll; 386 | } 387 | 388 | int main(int argc, char ** argv) 389 | { 390 | #if DEBUGEXEC 391 | debugexec("main", argc, argv); 392 | #endif 393 | #if !TRACEABLE 394 | untraceable(argv[0]); 395 | #endif 396 | argv[1] = xsh(argc, argv); 397 | fprintf(stderr, "%s%s%s: %s\n", argv[0], 398 | errno ? ": " : "", 399 | errno ? strerror(errno) : "", 400 | argv[1] ? argv[1] : "" 401 | ); 402 | return 1; 403 | } 404 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/pru.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -x 2 | echo "$0" "$@" 3 | ps $$ 4 | ps wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww $$ 5 | cat /proc/$$/cmdline 6 | touch $0.kk 7 | read ENTER 8 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/shc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaagr/shellscripts/dc2dd7addeb2e1bb794d9c459adffaafea757783/contrib/shc-3.8.9/shc -------------------------------------------------------------------------------- /contrib/shc-3.8.9/shc.1: -------------------------------------------------------------------------------- 1 | .TH shc 1 "Jun 18, 2003" "shc Version 3.8" 2 | .UC 4 3 | 4 | .SH "NAME" 5 | shc - Generic shell script compiler 6 | .SH "SYNOPSIS" 7 | .B shc 8 | [ \-\fBe\fP date ] 9 | [ \-\fBm\fP addr ] 10 | [ \-\fBi\fP iopt ] 11 | [ \-\fBx\fP cmnd ] 12 | .br 13 | [ \-\fBl\fP lopt ] 14 | [ \-\fBACDhTv\fP ] 15 | \-\fBf\fP script 16 | .SH "DESCRIPTION" 17 | .B shc 18 | creates a stripped binary executable version of the script 19 | specified with \fI\-f\fP on the command line. 20 | 21 | The binary version will get a \fI.x\fP extension appended 22 | and will usually be a bit larger in size than the original ascii code. 23 | Generated C source code is saved in a file with the extension \fI.x.c\fP 24 | 25 | If you supply an expiration date with the \fI\-e\fP option the 26 | compiled binary will refuse to run after the date specified. 27 | The message \fB"Please contact your provider"\fP will be displayed instead. 28 | This message can be changed with the \fI\-m\fP option. 29 | 30 | You can compile any kind of shell script, but you need to supply valid 31 | \fI\-i\fP, \fI\-x\fP and \fI\-l\fP options. 32 | 33 | The compiled binary will still be dependent on the shell specified 34 | in the first line of the shell code (i.e. #!/bin/sh), thus \fBshc\fP does not create 35 | completely independent binaries. 36 | 37 | \fBshc\fP itself is not a compiler such as cc, it rather encodes and 38 | encrypts a shell script and generates C source code with the added expiration 39 | capability. It then uses the system compiler to compile a stripped binary 40 | which behaves exactly like the original script. Upon execution, the compiled binary 41 | will decrypt and execute the code with the shell \fI-c\fP option. 42 | Unfortunatelly, it will not give you any speed improvement as a real C program would. 43 | 44 | \fBshc\fP's main purpose is to protect your shell scripts from modification or 45 | inspection. You can use it if you wish to distribute your scripts but don't 46 | want them to be easily readable by other people. 47 | .SH "OPTIONS" 48 | The command line options are: 49 | .TP 50 | .B -e date 51 | Expiration date in dd/mm/yyyy format [none] 52 | .TP 53 | .B -m message 54 | message to display upon expiration ["Please contact your provider"] 55 | .TP 56 | .B -f script_name 57 | File name of the script to compile 58 | .TP 59 | .B -i inline_option 60 | Inline option for the shell interpreter i.e: -e 61 | .TP 62 | .B -x comand 63 | eXec command, as a printf format i.e: exec(\\\\'%s\\\\',@ARGV); 64 | .TP 65 | .B -l last_option 66 | Last shell option i.e: -- 67 | .TP 68 | .B -r 69 | Relax security. Make a redistributable binary which executes on 70 | different systems running the same operating system. 71 | .TP 72 | .B -v 73 | Verbose compilation 74 | .TP 75 | .B -D 76 | Switch on debug exec calls 77 | .TP 78 | .B -T 79 | Allow binary to be traceable (using strace, ptrace, truss, etc.) 80 | .TP 81 | .B -C 82 | Display license and exit 83 | .TP 84 | .B -A 85 | Display abstract and exit 86 | .TP 87 | .B -h 88 | Display help and exit 89 | .SH "ENVIRONMENT VARIABLES" 90 | .TP 91 | .B CC 92 | C compiler command [cc] 93 | .TP 94 | .B CFLAGS 95 | C compiler flags [none] 96 | .SH "EXAMPLES" 97 | .SM 98 | Compile a script which can be run on other systems with the trace 99 | option enabled: 100 | 101 | example% \fBshc\fP -v -r -T -f myscript 102 | .SH "BUGS" 103 | The maximum size of the script that could be executed once compiled is limited 104 | by the operating system configuration parameter 105 | .B _SC_ARG_MAX 106 | (see 107 | .BR sysconf ( 2 )\c 108 | ) 109 | .SH "AUTHOR" 110 | Francisco Rosales 111 | 112 | .SH "REPORT BUGS TO" 113 | the author. 114 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/shc.README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaagr/shellscripts/dc2dd7addeb2e1bb794d9c459adffaafea757783/contrib/shc-3.8.9/shc.README -------------------------------------------------------------------------------- /contrib/shc-3.8.9/shc.c: -------------------------------------------------------------------------------- 1 | shc-3.8.9.c -------------------------------------------------------------------------------- /contrib/shc-3.8.9/shc.html: -------------------------------------------------------------------------------- 1 | Content-type: text/html 2 | 3 | Manpage of shc 4 | 5 |

shc

6 | Section: User Commands (1)
Updated: Jun 18, 2003
Index 7 | Return to Main Contents
8 | 9 | 10 |

11 |   12 |

NAME

13 | 14 | shc - Generic shell script compiler 15 |   16 |

SYNOPSIS

17 | 18 | shc 19 | 20 | [ -e date ] 21 | [ -m addr ] 22 | [ -i iopt ] 23 | [ -x cmnd ] 24 |
25 | 26 | [ -l lopt ] 27 | [ -ACDhTv ] 28 | -f script 29 |   30 |

DESCRIPTION

31 | 32 | shc 33 | 34 | creates a stripped binary executable version of the script 35 | specified with -f on the command line. 36 |

37 | The binary version will get a .x extension appended 38 | and will usually be a bit larger in size than the original ascii code. 39 | Generated C source code is saved in a file with the extension .x.c 40 |

41 | If you supply an expiration date with the -e option the 42 | compiled binary will refuse to run after the date specified. 43 | The message "Please contact your provider" will be displayed instead. 44 | This message can be changed with the -m option. 45 |

46 | You can compile any kind of shell script, but you need to supply valid 47 | -i, -x and -l options. 48 |

49 | The compiled binary will still be dependent on the shell specified 50 | in the first line of the shell code (i.e. #!/bin/sh), thus shc does not create 51 | completely independent binaries. 52 |

53 | shc itself is not a compiler such as cc, it rather encodes and 54 | encrypts a shell script and generates C source code with the added expiration 55 | capability. It then uses the system compiler to compile a stripped binary 56 | which behaves exactly like the original script. Upon execution, the compiled binary 57 | will decrypt and execute the code with the shell -c option. 58 | Unfortunatelly, it will not give you any speed improvement as a real C program would. 59 |

60 | shc's main purpose is to protect your shell scripts from modification or 61 | inspection. You can use it if you wish to distribute your scripts but don't 62 | want them to be easily readable by other people. 63 |   64 |

OPTIONS

65 | 66 | The command line options are: 67 |
68 |
-e date 69 | 70 |
71 | Expiration date in dd/mm/yyyy format [none] 72 |
-m message 73 | 74 |
75 | message to display upon expiration ["Please contact your provider"] 76 |
-f script_name 77 | 78 |
79 | File name of the script to compile 80 |
-i inline_option 81 | 82 |
83 | Inline option for the shell interpreter i.e: -e 84 |
-x comand 85 | 86 |
87 | eXec command, as a printf format i.e: exec(\\'%s\\',@ARGV); 88 |
-l last_option 89 | 90 |
91 | Last shell option i.e: -- 92 |
-r 93 | 94 |
95 | Relax security. Make a redistributable binary which executes on 96 | different systems running the same operating system. 97 |
-v 98 | 99 |
100 | Verbose compilation 101 |
-D 102 | 103 |
104 | Switch on debug exec calls 105 |
-T 106 | 107 |
108 | Allow binary to be traceable (using strace, ptrace, truss, etc.) 109 |
-C 110 | 111 |
112 | Display license and exit 113 |
-A 114 | 115 |
116 | Display abstract and exit 117 |
-h 118 | 119 |
120 | Display help and exit 121 |
122 |   123 |

ENVIRONMENT VARIABLES

124 | 125 |
126 |
CC 127 | 128 |
129 | C compiler command [cc] 130 |
CFLAGS 131 | 132 |
133 | C compiler flags [none] 134 |
135 |   136 |

EXAMPLES

137 | 138 | Compile a script which can be run on other systems with the trace 139 | option enabled: 140 |

141 |
  example% shc -v -r -T -f myscript 142 |   143 |

BUGS

144 | 145 | The maximum size of the script that could be executed once compiled is limited 146 | by the operating system configuration parameter 147 | _SC_ARG_MAX 148 | 149 | (see 150 | sysconf(2)) 151 |   152 |

AUTHOR

153 | 154 | Francisco Rosales 155 | <frosal@fi.upm.es> 156 |   157 |

REPORT BUGS TO

158 | 159 | the author. 160 |

161 | 162 |


163 |  

Index

164 |
165 |
NAME
166 |
SYNOPSIS
167 |
DESCRIPTION
168 |
OPTIONS
169 |
ENVIRONMENT VARIABLES
170 |
EXAMPLES
171 |
BUGS
172 |
AUTHOR
173 |
REPORT BUGS TO
174 |
175 |
176 | This document was created by 177 | man2html, 178 | using the manual pages.
179 | Time: 15:46:31 GMT, July 08, 2004 180 | 181 | 182 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/test.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | echo "\$@ is $@" 3 | echo "command line: $0 $*" 4 | echo "hello world" 5 | # Added 6 | echo "[$$] PAUSED... Hit return!" 7 | read DUMMY 8 | exit 0 9 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/test.csh: -------------------------------------------------------------------------------- 1 | #!/bin/csh -x 2 | echo Hello world 3 | 4 | # A comment 5 | 6 | exit 0 7 | -------------------------------------------------------------------------------- /contrib/shc-3.8.9/test.ksh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/ksh -x 2 | echo "\$@ is $@" 3 | echo "command line: $0 $*" 4 | echo "hello world" 5 | # Added 6 | echo "[$$] PAUSED... Hit return!" 7 | read DUMMY 8 | exit 0 9 | -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/changelog.txt: -------------------------------------------------------------------------------- 1 | ----- 2 | 0.1.1 3 | ----- 4 | 5 | Added this changelog. 6 | 7 | Added an internal function for getting absolute paths in the generic 8 | script loader-extended.sh. Normal shells are now independent of the 9 | external commands getabspath and awk. 10 | 11 | Fixed detection of the optional external command getabspath. This time 12 | also, it will only be used if the newly added internal function doesn't 13 | work for the shell. 14 | 15 | No other changes were made in the other scripts. 16 | 17 | --- 18 | 0.1 19 | --- 20 | 21 | First Presentable Release 22 | -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/compiler: -------------------------------------------------------------------------------- 1 | compiler-20141212.gawk -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/loader.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | # ---------------------------------------------------------------------- 5 | 6 | # loader.bash 7 | # 8 | # This script implements Shell Script Loader for all versions of bash 9 | # starting 2.04. 10 | # 11 | # The script works faster with associative arrays. To use associative 12 | # arrays, run the script with bash 4.2 or newer. You can also enable 13 | # usage of associative arrays with 4.0 or 4.1 by including it globally; 14 | # that is, not include the script with 'source' or '.' inside any 15 | # function. 16 | # 17 | # Please see loader.txt for more info on how to use this script. 18 | # 19 | # This script complies with the Requiring Specifications of 20 | # Shell Script Loader version 0 (RS0) 21 | # 22 | # Version: 0.1 23 | # 24 | # Author: konsolebox 25 | # Copyright Free / Public Domain 26 | # Aug. 29, 2009 (Last Updated 2011/04/08) 27 | 28 | # Limitations of Shell Script Loader with integers and associative 29 | # arrays: 30 | # 31 | # With versions of bash earlier than 4.2, a variable can't be declared 32 | # global with the use of 'typeset' and 'declare' builtins when inside a 33 | # function. With Shell Script Loader, shell scripts are always loaded 34 | # inside functions so variables that can only be declared using the said 35 | # builtin commands cannot be declared global. These kinds of variables 36 | # that cannot be declared global are the newer types like associative 37 | # arrays and integers. Unlike Zsh, we can add '-g' as an option to 38 | # 'typeset' or 'declare' to declare global variables but we can't do 39 | # that in bash. 40 | # 41 | # For example, if we do something like 42 | # 43 | # > include file.sh 44 | # 45 | # Where the contents of file.sh is 46 | # 47 | # > declare -A associative_array 48 | # > declare -i integer 49 | # 50 | # After include() ends, the variables automatically gets lost since 51 | # variables are only local and not global if declare or typeset is used 52 | # inside a function and we know that include() is a function. 53 | # 54 | # However it's safe to declare other types of variables like indexed 55 | # arrays in simpler way. 56 | # 57 | # For example: 58 | # 59 | # > SIMPLEVAR='' 60 | # > ARRAYVAR=() 61 | # 62 | # These declarations are even just optional. 63 | # 64 | # Note: These conditions do not apply if you only plan to run the code 65 | # in compiled form since you no longer have to use the functions. For 66 | # more info about compilation, please see the available compilers of 67 | # Shell Script Loader. 68 | 69 | 70 | # ---------------------------------------------------------------------- 71 | 72 | 73 | if [ "$LOADER_ACTIVE" = true ]; then 74 | echo "loader: loader cannot be loaded twice." 75 | exit 1 76 | fi 77 | if [ -z "$BASH_VERSION" ]; then 78 | echo "loader: bash is needed to run this script." 79 | exit 1 80 | fi 81 | case "$BASH" in 82 | sh|*/sh) 83 | echo "loader: this script doesn't work if bash is running sh-emulation mode." 84 | exit 1 85 | ;; 86 | esac 87 | if ! [ "$BASH_VERSINFO" -ge 3 -o "$BASH_VERSION" '>' 2.03 ]; then 88 | echo "loader: this script is only compatible with versions of bash not earlier than 2.04." 89 | exit 1 90 | fi 91 | if ! declare -a LOADER_TEST0; then 92 | echo "loader: it seems that this build of bash does not include support for arrays." 93 | exit 1 94 | fi 95 | 96 | 97 | #### PUBLIC VARIABLES #### 98 | 99 | LOADER_ACTIVE=true 100 | LOADER_RS=0 101 | LOADER_VERSION=0.1 102 | 103 | 104 | #### PRIVATE VARIABLES #### 105 | 106 | LOADER_CS=() 107 | LOADER_CS_I=0 108 | LOADER_PATHS=() 109 | 110 | if [[ BASH_VERSINFO -ge 5 || (BASH_VERSINFO -eq 4 && BASH_VERSINFO[1] -ge 2) ]]; then 111 | declare -g -A LOADER_FLAGS=() 112 | declare -g -A LOADER_PATHS_FLAGS=() 113 | LOADER_USEAARRAYS=true 114 | elif [[ BASH_VERSINFO -eq 4 ]] && declare -A LOADER_TEST1 &>/dev/null && ! local LOADER_TEST2 &>/dev/null; then 115 | declare -A LOADER_FLAGS=() 116 | declare -A LOADER_PATHS_FLAGS=() 117 | LOADER_USEAARRAYS=true 118 | else 119 | LOADER_USEAARRAYS=false 120 | fi 121 | 122 | 123 | #### PUBLIC FUNCTIONS #### 124 | 125 | function load { 126 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." load 127 | 128 | case "$1" in 129 | '') 130 | loader_fail "file expression cannot be null." load "$@" 131 | ;; 132 | /*|./*|../*) 133 | if [[ -f $1 ]]; then 134 | loader_getabspath "$1" 135 | 136 | [[ -r $__ ]] || loader_fail "file not readable: $__" load "$@" 137 | 138 | shift 139 | loader_load "$@" 140 | 141 | return 142 | fi 143 | ;; 144 | *) 145 | for __ in "${LOADER_PATHS[@]}"; do 146 | [[ -f $__/$1 ]] || continue 147 | 148 | loader_getabspath "$__/$1" 149 | 150 | [[ -r $__ ]] || loader_fail "found file not readable: $__" load "$@" 151 | 152 | loader_flag_ "$1" 153 | 154 | shift 155 | loader_load "$@" 156 | 157 | return 158 | done 159 | ;; 160 | esac 161 | 162 | loader_fail "file not found: $1" load "$@" 163 | } 164 | 165 | function include { 166 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." include 167 | 168 | case "$1" in 169 | '') 170 | loader_fail "file expression cannot be null." include "$@" 171 | ;; 172 | /*|./*|../*) 173 | loader_getabspath "$1" 174 | 175 | loader_flagged "$__" && \ 176 | return 177 | 178 | if [[ -f $__ ]]; then 179 | [[ -r $__ ]] || loader_fail "file not readable: $__" include "$@" 180 | 181 | shift 182 | loader_load "$@" 183 | 184 | return 185 | fi 186 | ;; 187 | *) 188 | loader_flagged "$1" && \ 189 | return 190 | 191 | for __ in "${LOADER_PATHS[@]}"; do 192 | loader_getabspath "$__/$1" 193 | 194 | if loader_flagged "$__"; then 195 | loader_flag_ "$1" 196 | 197 | return 198 | elif [[ -f $__ ]]; then 199 | [[ -r $__ ]] || loader_fail "found file not readable: $__" include "$@" 200 | 201 | loader_flag_ "$1" 202 | 203 | shift 204 | loader_load "$@" 205 | 206 | return 207 | fi 208 | done 209 | ;; 210 | esac 211 | 212 | loader_fail "file not found: $1" include "$@" 213 | } 214 | 215 | function call { 216 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." call 217 | 218 | case "$1" in 219 | '') 220 | loader_fail "file expression cannot be null." call "$@" 221 | ;; 222 | /*|./*|../*) 223 | if [[ -f $1 ]]; then 224 | loader_getabspath "$1" 225 | 226 | [[ -r $__ ]] || loader_fail "file not readable: $__" call "$@" 227 | 228 | ( 229 | shift 230 | loader_load "$@" 231 | ) 232 | 233 | return 234 | fi 235 | ;; 236 | *) 237 | for __ in "${LOADER_PATHS[@]}"; do 238 | [[ -f $__/$1 ]] || continue 239 | 240 | loader_getabspath "$__/$1" 241 | 242 | [[ -r $__ ]] || loader_fail "found file not readable: $__" call "$@" 243 | 244 | ( 245 | loader_flag_ "$1" 246 | 247 | shift 248 | loader_load "$@" 249 | ) 250 | 251 | return 252 | done 253 | ;; 254 | esac 255 | 256 | loader_fail "file not found: $1" call "$@" 257 | } 258 | 259 | function loader_addpath { 260 | for __ in "$@"; do 261 | [[ -d $__ ]] || loader_fail "directory not found: $__" loader_addpath "$@" 262 | [[ -x $__ ]] || loader_fail "directory not accessible: $__" loader_addpath "$@" 263 | [[ -r $__ ]] || loader_fail "directory not searchable: $__" loader_addpath "$@" 264 | loader_getabspath_ "$__/." 265 | loader_addpath_ "$__" 266 | done 267 | } 268 | 269 | function loader_flag { 270 | [[ $# -eq 1 ]] || loader_fail "function requires a single argument." loader_flag "$@" 271 | loader_getabspath "$1" 272 | loader_flag_ "$__" 273 | } 274 | 275 | function loader_reset { 276 | if [[ $# -eq 0 ]]; then 277 | loader_resetflags 278 | loader_resetpaths 279 | elif [[ $1 = flags ]]; then 280 | loader_resetflags 281 | elif [[ $1 = paths ]]; then 282 | loader_resetpaths 283 | else 284 | loader_fail "invalid argument: $1" loader_reset "$@" 285 | fi 286 | } 287 | 288 | function loader_finish { 289 | LOADER_ACTIVE=false 290 | 291 | loader_unsetvars 292 | 293 | unset \ 294 | load \ 295 | include \ 296 | call \ 297 | loader_addpath \ 298 | loader_addpath_ \ 299 | loader_fail \ 300 | loader_finish \ 301 | loader_flag \ 302 | loader_flag_ \ 303 | loader_flagged \ 304 | loader_getabspath \ 305 | loader_getabspath_ \ 306 | loader_load \ 307 | loader_load_ \ 308 | loader_reset \ 309 | loader_resetflags \ 310 | loader_resetpaths \ 311 | loader_unsetvars \ 312 | LOADER_CS \ 313 | LOADER_CS_I \ 314 | LOADER_PATHS 315 | } 316 | 317 | 318 | #### PRIVATE FUNCTIONS #### 319 | 320 | function loader_load { 321 | loader_flag_ "$__" 322 | 323 | LOADER_CS[LOADER_CS_I++]=$__ 324 | 325 | loader_load_ "$@" 326 | 327 | __=$? 328 | 329 | unset LOADER_CS\[--LOADER_CS_I\] 330 | 331 | return "$__" 332 | } 333 | 334 | function loader_load_ { 335 | . "$__" 336 | } 337 | 338 | function loader_getabspath { 339 | case "$1" in 340 | .|'') 341 | case "$PWD" in 342 | /) 343 | __=/. 344 | ;; 345 | *) 346 | __=${PWD%/} 347 | ;; 348 | esac 349 | ;; 350 | ..|../*|*/..|*/../*|./*|*/.|*/./*|*//*) 351 | loader_getabspath_ "$1" 352 | ;; 353 | /*) 354 | __=$1 355 | ;; 356 | *) 357 | __=${PWD%/}/$1 358 | ;; 359 | esac 360 | } 361 | 362 | function loader_fail { 363 | local MESSAGE=$1 FUNC=$2 MAIN A I 364 | shift 2 365 | 366 | if [[ -n $0 && ! "${0##*/}" = "${BASH##*/}" ]]; then 367 | MAIN=$0 368 | else 369 | MAIN='(main)' 370 | fi 371 | 372 | { 373 | echo "loader: ${FUNC}(): ${MESSAGE}" 374 | echo 375 | 376 | echo " current scope:" 377 | if [[ LOADER_CS_I -gt 0 ]]; then 378 | echo " ${LOADER_CS[LOADER_CS_I - 1]}" 379 | else 380 | echo " $MAIN" 381 | fi 382 | echo 383 | 384 | if [[ $# -gt 0 ]]; then 385 | echo " command:" 386 | echo -n " $FUNC" 387 | for A; do 388 | echo -n " \"$A\"" 389 | done 390 | echo 391 | echo 392 | fi 393 | 394 | if [[ LOADER_CS_I -gt 0 ]]; then 395 | echo " call stack:" 396 | echo " $MAIN" 397 | for A in "${LOADER_CS[@]}"; do 398 | echo " -> $A" 399 | done 400 | echo 401 | fi 402 | 403 | echo " search paths:" 404 | if [[ ${#LOADER_PATHS[@]} -gt 0 ]]; then 405 | for A in "${LOADER_PATHS[@]}"; do 406 | echo " $A" 407 | done 408 | else 409 | echo " (empty)" 410 | fi 411 | echo 412 | 413 | echo " working directory:" 414 | echo " $PWD" 415 | echo 416 | } >&2 417 | 418 | exit 1 419 | } 420 | 421 | 422 | #### VERSION DEPENDENT FUNCTIONS AND VARIABLES #### 423 | 424 | if [[ $LOADER_USEAARRAYS = true ]]; then 425 | function loader_addpath_ { 426 | if [[ -z ${LOADER_PATHS_FLAGS[$1]} ]]; then 427 | LOADER_PATHS[${#LOADER_PATHS[@]}]=$1 428 | LOADER_PATHS_FLAGS[$1]=. 429 | fi 430 | } 431 | 432 | function loader_flag_ { 433 | LOADER_FLAGS[$1]=. 434 | } 435 | 436 | function loader_flagged { 437 | [[ -n ${LOADER_FLAGS[$1]} ]] 438 | } 439 | 440 | function loader_resetflags { 441 | LOADER_FLAGS=() 442 | } 443 | 444 | function loader_resetpaths { 445 | LOADER_PATHS=() 446 | LOADER_PATHS_FLAGS=() 447 | } 448 | 449 | function loader_unsetvars { 450 | unset LOADER_FLAGS LOADER_PATHS_FLAGS 451 | } 452 | else 453 | function loader_addpath_ { 454 | for __ in "${LOADER_PATHS[@]}"; do 455 | [[ $1 = "$__" ]] && \ 456 | return 457 | done 458 | 459 | LOADER_PATHS[${#LOADER_PATHS[@]}]=$1 460 | } 461 | 462 | function loader_flag_ { 463 | local V 464 | V=${1//./_dt_} 465 | V=${V// /_sp_} 466 | V=${V//\//_sl_} 467 | V=LOADER_FLAGS_${V//[^[:alnum:]_]/_ot_} 468 | eval "$V=." 469 | } 470 | 471 | function loader_flagged { 472 | local V 473 | V=${1//./_dt_} 474 | V=${V// /_sp_} 475 | V=${V//\//_sl_} 476 | V=LOADER_FLAGS_${V//[^[:alnum:]_]/_ot_} 477 | [[ -n ${!V} ]] 478 | } 479 | 480 | function loader_resetflags { 481 | local IFS=' ' 482 | unset ${!LOADER_FLAGS_*} 483 | } 484 | 485 | function loader_resetpaths { 486 | LOADER_PATHS=() 487 | } 488 | 489 | function loader_unsetvars { 490 | loader_resetflags 491 | } 492 | fi 493 | 494 | if [[ BASH_VERSINFO -ge 3 ]]; then 495 | eval " 496 | function loader_getabspath_ { 497 | local -a T1 T2 498 | local -i I=0 499 | local IFS=/ A 500 | 501 | case \"\$1\" in 502 | /*) 503 | read -r -a T1 <<< \"\$1\" 504 | ;; 505 | *) 506 | read -r -a T1 <<< \"/\$PWD/\$1\" 507 | ;; 508 | esac 509 | 510 | T2=() 511 | 512 | for A in \"\${T1[@]}\"; do 513 | case \"\$A\" in 514 | ..) 515 | [[ I -ne 0 ]] && unset T2\\[--I\\] 516 | continue 517 | ;; 518 | .|'') 519 | continue 520 | ;; 521 | esac 522 | 523 | T2[I++]=\$A 524 | done 525 | 526 | case \"\$1\" in 527 | */) 528 | [[ I -ne 0 ]] && __=\"/\${T2[*]}/\" || __=/ 529 | ;; 530 | *) 531 | [[ I -ne 0 ]] && __=\"/\${T2[*]}\" || __=/. 532 | ;; 533 | esac 534 | } 535 | " 536 | elif [[ $BASH_VERSION = 2.05b ]]; then 537 | eval " 538 | function loader_getabspath_ { 539 | local -a T=() 540 | local -i I=0 541 | local IFS=/ A 542 | 543 | case \"\$1\" in 544 | /*) 545 | __=\$1 546 | ;; 547 | *) 548 | __=/\$PWD/\$1 549 | ;; 550 | esac 551 | 552 | while read -r -d / A; do 553 | case \"\$A\" in 554 | ..) 555 | [[ I -ne 0 ]] && unset T\\[--I\\] 556 | continue 557 | ;; 558 | .|'') 559 | continue 560 | ;; 561 | esac 562 | 563 | T[I++]=\$A 564 | done <<< \"\$__/\" 565 | 566 | case \"\$1\" in 567 | */) 568 | [[ I -ne 0 ]] && __=\"/\${T[*]}/\" || __=/ 569 | ;; 570 | *) 571 | [[ I -ne 0 ]] && __=\"/\${T[*]}\" || __=/. 572 | ;; 573 | esac 574 | } 575 | " 576 | else 577 | eval " 578 | function loader_getabspath_ { 579 | local -a T=() 580 | local -i I=0 581 | local IFS=/ A 582 | 583 | case \"\$1\" in 584 | /*) 585 | __=\$1 586 | ;; 587 | *) 588 | __=/\$PWD/\$1 589 | ;; 590 | esac 591 | 592 | while read -r -d / A; do 593 | case \"\$A\" in 594 | ..) 595 | [[ I -ne 0 ]] && unset T\\[--I\\] 596 | continue 597 | ;; 598 | .|'') 599 | continue 600 | ;; 601 | esac 602 | 603 | T[I++]=\$A 604 | done << . 605 | \$__/ 606 | . 607 | 608 | case \"\$1\" in 609 | */) 610 | [[ I -ne 0 ]] && __=\"/\${T[*]}/\" || __=/ 611 | ;; 612 | *) 613 | [[ I -ne 0 ]] && __=\"/\${T[*]}\" || __=/. 614 | ;; 615 | esac 616 | } 617 | " 618 | fi 619 | 620 | unset LOADER_TEST0 LOADER_TEST1 LOADER_TEST2 LOADER_USEAARRAYS 621 | 622 | 623 | # ---------------------------------------------------------------------- 624 | 625 | # * Using 'set -- $VAR' to split strings inside variables will sometimes 626 | # yield different strings if one of the strings contain globs 627 | # characters like *, ? and the brackets [ and ] that are also valid 628 | # characters in filenames. 629 | 630 | # * Using 'read -a' to split strings to arrays yields elements 631 | # that contain invalid characters when a null token is found. 632 | # (bash versions < 3.0) 633 | 634 | # ---------------------------------------------------------------------- 635 | -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/loader.ksh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ksh 2 | 3 | 4 | # ---------------------------------------------------------------------- 5 | 6 | # loader.ksh 7 | # 8 | # This script implements Shell Script Loader for ksh; both the original 9 | # (KornShell 93+) and the public domain (PD KSH) Korn shell. 10 | # 11 | # Please see loader.txt for more info on how to use this script. 12 | # 13 | # This script complies with the Requiring Specifications of 14 | # Shell Script Loader version 0 (RS0) 15 | # 16 | # Version: 0.1 17 | # 18 | # Author: konsolebox 19 | # Copyright Free / Public Domain 20 | # Aug. 29, 2009 (Last Updated 2011/04/08) 21 | 22 | # Limitations of Shell Script Loader in PD KSH: 23 | # 24 | # In PD KSH (not the Ksh 93+), typeset declarations inside functions 25 | # always make variables only available within the encapsulating function 26 | # therefore scripts that have typeset declarations that are meant to 27 | # create global variables when called within a loader function like 28 | # include() will only have visibility inside include(). 29 | # 30 | # Array indices in PD KSH are currently limited to the range of 0 31 | # through 1023 but this value is big enough for the list of search paths 32 | # and for the call stack. 33 | 34 | # ---------------------------------------------------------------------- 35 | 36 | 37 | if [ "$LOADER_ACTIVE" = true ]; then 38 | echo "loader: loader cannot be loaded twice." 39 | exit 1 40 | fi 41 | if [ -n "$KSH_VERSION" ]; then 42 | LOADER_KSH_VERSION=1 43 | elif 44 | ( eval 'test -n "${.sh.version}" && exit 10'; ) >/dev/null 2>&1 45 | [ "$?" -eq 10 ] 46 | then 47 | LOADER_KSH_VERSION=0 48 | elif [ "$ZSH_NAME" = ksh ]; then 49 | echo "loader: emulated ksh from zsh does not work with this script." 50 | exit 1 51 | else 52 | echo "loader: ksh is needed to run this script." 53 | exit 1 54 | fi 55 | 56 | 57 | #### PUBLIC VARIABLES #### 58 | 59 | LOADER_ACTIVE=true 60 | LOADER_RS=0 61 | LOADER_VERSION=0.1 62 | 63 | 64 | #### PRIVATE VARIABLES #### 65 | 66 | set -A LOADER_CS 67 | set -A LOADER_PATHS 68 | LOADER_CS_I=0 69 | 70 | 71 | #### PUBLIC FUNCTIONS #### 72 | 73 | load() { 74 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." load 75 | 76 | case "$1" in 77 | '') 78 | loader_fail "file expression cannot be null." load "$@" 79 | ;; 80 | /*|./*|../*) 81 | if [[ -f $1 ]]; then 82 | loader_getabspath "$1" 83 | 84 | [[ -r $__ ]] || loader_fail "file not readable: $__" load "$@" 85 | 86 | shift 87 | loader_load "$@" 88 | 89 | return 90 | fi 91 | ;; 92 | *) 93 | for __ in "${LOADER_PATHS[@]}"; do 94 | [[ -f $__/$1 ]] || continue 95 | 96 | loader_getabspath "$__/$1" 97 | 98 | [[ -r $__ ]] || loader_fail "found file not readable: $__" load "$@" 99 | 100 | loader_flag_ "$1" 101 | 102 | shift 103 | loader_load "$@" 104 | 105 | return 106 | done 107 | ;; 108 | esac 109 | 110 | loader_fail "file not found: $1" load "$@" 111 | } 112 | 113 | include() { 114 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." include 115 | 116 | case "$1" in 117 | '') 118 | loader_fail "file expression cannot be null." include "$@" 119 | ;; 120 | /*|./*|../*) 121 | loader_getabspath "$1" 122 | 123 | loader_flagged "$__" && \ 124 | return 125 | 126 | if [[ -f $__ ]]; then 127 | [[ -r $__ ]] || loader_fail "file not readable: $__" include "$@" 128 | 129 | shift 130 | loader_load "$@" 131 | 132 | return 133 | fi 134 | ;; 135 | *) 136 | loader_flagged "$1" && \ 137 | return 138 | 139 | for __ in "${LOADER_PATHS[@]}"; do 140 | loader_getabspath "$__/$1" 141 | 142 | if loader_flagged "$__"; then 143 | loader_flag_ "$1" 144 | 145 | return 146 | elif [[ -f $__ ]]; then 147 | [[ -r $__ ]] || loader_fail "found file not readable: $__" include "$@" 148 | 149 | loader_flag_ "$1" 150 | 151 | shift 152 | loader_load "$@" 153 | 154 | return 155 | fi 156 | done 157 | ;; 158 | esac 159 | 160 | loader_fail "file not found: $1" include "$@" 161 | } 162 | 163 | call() { 164 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." call 165 | 166 | case "$1" in 167 | '') 168 | loader_fail "file expression cannot be null." call "$@" 169 | ;; 170 | /*|./*|../*) 171 | if [[ -f $1 ]]; then 172 | loader_getabspath "$1" 173 | 174 | [[ -r $__ ]] || loader_fail "file not readable: $__" call "$@" 175 | 176 | ( 177 | shift 178 | loader_load "$@" 179 | ) 180 | 181 | return 182 | fi 183 | ;; 184 | *) 185 | for __ in "${LOADER_PATHS[@]}"; do 186 | [[ -f $__/$1 ]] || continue 187 | 188 | loader_getabspath "$__/$1" 189 | 190 | [[ -r $__ ]] || loader_fail "found file not readable: $__" call "$@" 191 | 192 | ( 193 | loader_flag_ "$1" 194 | 195 | shift 196 | loader_load "$@" 197 | ) 198 | 199 | return 200 | done 201 | ;; 202 | esac 203 | 204 | loader_fail "file not found: $1" call "$@" 205 | } 206 | 207 | loader_addpath() { 208 | for __ in "$@"; do 209 | [[ -d $__ ]] || loader_fail "directory not found: $__" loader_addpath "$@" 210 | [[ -x $__ ]] || loader_fail "directory not accessible: $__" loader_addpath "$@" 211 | [[ -r $__ ]] || loader_fail "directory not searchable: $__" loader_addpath "$@" 212 | loader_getabspath_ "$__/." 213 | loader_addpath_ "$__" 214 | done 215 | } 216 | 217 | loader_flag() { 218 | [[ $# -eq 1 ]] || loader_fail "function requires a single argument." loader_flag "$@" 219 | loader_getabspath "$1" 220 | loader_flag_ "$__" 221 | } 222 | 223 | loader_reset() { 224 | if [[ $# -eq 0 ]]; then 225 | loader_resetflags 226 | loader_resetpaths 227 | elif [[ $1 = flags ]]; then 228 | loader_resetflags 229 | elif [[ $1 = paths ]]; then 230 | loader_resetpaths 231 | else 232 | loader_fail "invalid argument: $1" loader_reset "$@" 233 | fi 234 | } 235 | 236 | loader_finish() { 237 | LOADER_ACTIVE=false 238 | 239 | loader_unsetvars 240 | 241 | unset \ 242 | load \ 243 | include \ 244 | call \ 245 | loader_addpath \ 246 | loader_addpath_ \ 247 | loader_fail \ 248 | loader_finish \ 249 | loader_flag \ 250 | loader_flag_ \ 251 | loader_flagged \ 252 | loader_getabspath \ 253 | loader_getabspath_ \ 254 | loader_load \ 255 | loader_load_ \ 256 | loader_reset \ 257 | loader_unsetvars \ 258 | LOADER_CS \ 259 | LOADER_CS_I \ 260 | LOADER_KSH_VERSION \ 261 | LOADER_PATHS 262 | } 263 | 264 | 265 | #### PRIVATE FUNCTIONS #### 266 | 267 | loader_addpath_() { 268 | for __ in "${LOADER_PATHS[@]}"; do 269 | [[ $1 = $__ ]] && \ 270 | return 271 | done 272 | 273 | LOADER_PATHS[${#LOADER_PATHS[@]}]=$1 274 | } 275 | 276 | loader_load() { 277 | loader_flag_ "$__" 278 | 279 | LOADER_CS[++LOADER_CS_I]=$__ 280 | 281 | loader_load_ "$@" 282 | 283 | __=$? 284 | 285 | LOADER_CS[LOADER_CS_I--]= 286 | 287 | return "$__" 288 | } 289 | 290 | loader_load_() { 291 | . "$__" 292 | } 293 | 294 | loader_getabspath() { 295 | case "$1" in 296 | .|'') 297 | case "$PWD" in 298 | /) 299 | __=/. 300 | ;; 301 | *) 302 | __=${PWD%/} 303 | ;; 304 | esac 305 | ;; 306 | ..|../*|*/..|*/../*|./*|*/.|*/./*|*//*) 307 | loader_getabspath_ "$1" 308 | ;; 309 | /*) 310 | __=$1 311 | ;; 312 | *) 313 | __=${PWD%/}/$1 314 | ;; 315 | esac 316 | } 317 | 318 | loader_fail() { 319 | typeset MESSAGE FUNC A I 320 | 321 | MESSAGE=$1 FUNC=$2 322 | shift 2 323 | 324 | { 325 | echo "loader: ${FUNC}(): ${MESSAGE}" 326 | echo 327 | 328 | echo " current scope:" 329 | if [[ LOADER_CS_I -gt 0 ]]; then 330 | echo " ${LOADER_CS[LOADER_CS_I]}" 331 | else 332 | echo " (main)" 333 | fi 334 | echo 335 | 336 | if [[ $# -gt 0 ]]; then 337 | echo " command:" 338 | echo -n " $FUNC" 339 | for A; do 340 | echo -n " \"$A\"" 341 | done 342 | echo 343 | echo 344 | fi 345 | 346 | if [[ LOADER_CS_I -gt 0 ]]; then 347 | echo " call stack:" 348 | echo " (main)" 349 | I=1 350 | while [[ I -le LOADER_CS_I ]]; do 351 | echo " -> ${LOADER_CS[I]}" 352 | (( ++I )) 353 | done 354 | echo 355 | fi 356 | 357 | echo " search paths:" 358 | if [[ ${#LOADER_PATHS[@]} -gt 0 ]]; then 359 | for A in "${LOADER_PATHS[@]}"; do 360 | echo " $A" 361 | done 362 | else 363 | echo " (empty)" 364 | fi 365 | echo 366 | 367 | echo " working directory:" 368 | echo " $PWD" 369 | echo 370 | } >&2 371 | 372 | exit 1 373 | } 374 | 375 | 376 | #### VERSION DEPENDENT FUNCTIONS AND VARIABLES #### 377 | 378 | if [[ $LOADER_KSH_VERSION = 0 ]]; then 379 | eval " 380 | LOADER_FLAGS=([.]=.) 381 | LOADER_PATHS_FLAGS=([.]=.) 382 | 383 | loader_addpath_() { 384 | if [[ -z \${LOADER_PATHS_FLAGS[\$1]} ]]; then 385 | LOADER_PATHS[\${#LOADER_PATHS[@]}]=\$1 386 | LOADER_PATHS_FLAGS[\$1]=. 387 | fi 388 | } 389 | 390 | loader_flag_() { 391 | LOADER_FLAGS[\$1]=. 392 | } 393 | 394 | loader_flagged() { 395 | [[ -n \${LOADER_FLAGS[\$1]} ]] 396 | } 397 | 398 | loader_resetflags() { 399 | LOADER_FLAGS=() 400 | } 401 | 402 | loader_resetpaths() { 403 | set -A LOADER_PATHS 404 | LOADER_PATHS_FLAGS=() 405 | } 406 | 407 | loader_unsetvars() { 408 | unset LOADER_FLAGS LOADER_PATHS_FLAGS 409 | } 410 | " 411 | 412 | if 413 | eval " 414 | __=. 415 | read __ <<< \"\$__\" 416 | [[ \$__ = '\".\"' ]] 417 | " 418 | then 419 | eval " 420 | function loader_getabspath_ { 421 | typeset T1 T2 422 | typeset -i I=0 423 | typeset IFS=/ A 424 | 425 | case \"\$1\" in 426 | /*) 427 | read -r -A T1 <<< \$1 428 | ;; 429 | *) 430 | read -r -A T1 <<< \$PWD/\$1 431 | ;; 432 | esac 433 | 434 | set -A T2 435 | 436 | for A in \"\${T1[@]}\"; do 437 | case \"\$A\" in 438 | ..) 439 | [[ I -ne 0 ]] && unset T2\\[--I\\] 440 | continue 441 | ;; 442 | .|'') 443 | continue 444 | ;; 445 | esac 446 | 447 | T2[I++]=\$A 448 | done 449 | 450 | case \"\$1\" in 451 | */) 452 | [[ I -ne 0 ]] && __=\"/\${T2[*]}/\" || __=/ 453 | ;; 454 | *) 455 | [[ I -ne 0 ]] && __=\"/\${T2[*]}\" || __=/. 456 | ;; 457 | esac 458 | } 459 | " 460 | else 461 | eval " 462 | function loader_getabspath_ { 463 | typeset T1 T2 464 | typeset -i I=0 465 | typeset IFS=/ A 466 | 467 | case \"\$1\" in 468 | /*) 469 | read -r -A T1 <<< \"\$1\" 470 | ;; 471 | *) 472 | read -r -A T1 <<< \"\$PWD/\$1\" 473 | ;; 474 | esac 475 | 476 | set -A T2 477 | 478 | for A in \"\${T1[@]}\"; do 479 | case \"\$A\" in 480 | ..) 481 | [[ I -ne 0 ]] && unset T2\\[--I\\] 482 | continue 483 | ;; 484 | .|'') 485 | continue 486 | ;; 487 | esac 488 | 489 | T2[I++]=\$A 490 | done 491 | 492 | case \"\$1\" in 493 | */) 494 | [[ I -ne 0 ]] && __=\"/\${T2[*]}/\" || __=/ 495 | ;; 496 | *) 497 | [[ I -ne 0 ]] && __=\"/\${T2[*]}\" || __=/. 498 | ;; 499 | esac 500 | } 501 | " 502 | fi 503 | else 504 | loader_addpath_() { 505 | for __ in "${LOADER_PATHS[@]}"; do 506 | [[ $1 = "$__" ]] && \ 507 | return 508 | done 509 | 510 | LOADER_PATHS[${#LOADER_PATHS[@]}]=$1 511 | } 512 | 513 | loader_flag_() { 514 | eval "LOADER_FLAGS_$(echo "$1" | sed 's/\./_dt_/g; s/\//_sl_/g; s/ /_sp_/g; s/[^[:alnum:]_]/_ot_/g')=." 515 | } 516 | 517 | loader_flagged() { 518 | eval "[[ -n \$LOADER_FLAGS_$(echo "$1" | sed 's/\./_dt_/g; s/\//_sl_/g; s/ /_sp_/g; s/[^[:alnum:]_]/_ot_/g') ]]" 519 | } 520 | 521 | loader_getabspath_() { 522 | typeset A T IFS=/ TOKENS I=0 J=0 523 | 524 | A=${1%/} 525 | 526 | if [[ -n $A ]]; then 527 | while :; do 528 | T=${A%%/*} 529 | 530 | case "$T" in 531 | ..) 532 | if [[ I -gt 0 ]]; then 533 | unset TOKENS\[--I\] 534 | else 535 | (( ++J )) 536 | fi 537 | ;; 538 | .|'') 539 | ;; 540 | *) 541 | TOKENS[I++]=$T 542 | ;; 543 | esac 544 | 545 | case "$A" in 546 | */*) 547 | A=${A#*/} 548 | ;; 549 | *) 550 | break 551 | ;; 552 | esac 553 | done 554 | fi 555 | 556 | __="/${TOKENS[*]}" 557 | 558 | if [[ $1 != /* ]]; then 559 | A=${PWD%/} 560 | 561 | while [[ J -gt 0 && -n $A ]]; do 562 | A=${A%/*} 563 | (( --J )) 564 | done 565 | 566 | [[ -n $A ]] && __=$A${__%/} 567 | fi 568 | 569 | if [[ $__ = / ]]; then 570 | [[ $1 != */ ]] && __=/. 571 | elif [[ $1 == */ ]]; then 572 | __=$__/ 573 | fi 574 | } 575 | 576 | loader_resetflags() { 577 | unset $(set | grep -a ^LOADER_FLAGS_ | cut -f 1 -d =) 578 | } 579 | 580 | loader_resetpaths() { 581 | set -A LOADER_PATHS 582 | } 583 | 584 | loader_unsetvars() { 585 | loader_resetflags 586 | } 587 | fi 588 | 589 | 590 | # ---------------------------------------------------------------------- 591 | 592 | # * In some if not all versions of ksh, "${@:X[:Y]}" always presents a 593 | # single null string if no positional parameter is matched. 594 | # 595 | # * In some versions of ksh, 'read <<< "$VAR"' includes '"' in the 596 | # string. 597 | # 598 | # * Using 'set -- $VAR' to split strings inside variables will sometimes 599 | # yield different strings if one of the strings contain globs 600 | # characters like *, ? and the brackets [ and ] that are also valid 601 | # characters in filenames. 602 | # 603 | # * Changing the IFS causes buggy behaviors in PD KSH. 604 | 605 | # ---------------------------------------------------------------------- 606 | -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/loader.txt: -------------------------------------------------------------------------------- 1 | Shell Script Loader 2 | ------------------- 3 | 4 | Preamble 5 | 6 | This document describes Shell Script Loader and its usage. It also 7 | serves as a co-describer for the Requiring Specifications of 8 | Shell Script Loader version 0 (RS0). 9 | 10 | 11 | Document Version 12 | 13 | 0.1 14 | 15 | 16 | Definitions 17 | 18 | shell script - a script that is acknowledged by the shell. 19 | 20 | co-shell-script - a shell script that is called by and works with 21 | another another shell script. 22 | 23 | complete path - refers to a path that clearly points to a file. A 24 | path that begins with /, ./ or ../ is considered as 25 | complete. 26 | 27 | partial path - refers to a path that implies a need for a prefix to 28 | make itself complete. A path that doesn't begin with 29 | /, ./, and ../ is considered as partial. 30 | 31 | absolute path - refers to a path that begins with /. 32 | 33 | clean absolute - refers to an absolute path that does not contain /./ 34 | or /../ in between. 35 | 36 | relative path - refers to a path that does not begin with /. 37 | 38 | flagged - a path to a file that is flagged is considered as 39 | already included. If a second attempt to load the 40 | file is made using the function include(), the file 41 | will just be ignored. 42 | 43 | 44 | What is Shell Script Loader? 45 | 46 | Shell Script Loader is a framework (in a helper script) that can be used 47 | by shell script based applications for easy loading of co-shell-scripts 48 | or subscripts. Using this utility a scripter can now be able to apply 49 | multi-file or module-oriented scripting or programming in shells just 50 | like the way they are always done in known languages like Perl, PHP and 51 | Ruby. There are many benefits with using module-oriented programming 52 | just like code sharing, portability, modularity, easy revisioning, easy 53 | restructuring, and reusability. 54 | 55 | The helper functions that the framework provides include load(), 56 | include(), call(), loader_addpath(), loader_flag(), loader_reset(), and 57 | loader_finish(). Among the said functions, load(), include() and call() 58 | are the ones that can be used to manipulate co-shell-scripts. 59 | 60 | 61 | Design 62 | 63 | Shell Script Loader has been carefully designed for stability, speed and 64 | efficiency with minimum sacrifice in readability of code's logic. 65 | Uniform coding style and structure also is very strict. 66 | 67 | 68 | Shell-Dependent Limitations 69 | 70 | Since co-shell-scripts are loaded through functions, variables inside 71 | co-shell-scripts are treated as if they were declared inside funtions. 72 | If a shell script requires a variable to be global, the scripter should 73 | consider how the shell creates variables inside functions without 74 | giving it a visibility or scope that is only local to the function. 75 | 76 | Some shells like Zsh (using "typeset -g"), Bash (using "declare -g" in 77 | versions 4.2 and newer) and Ksh (functions not declared with the 78 | "function" keyword) have full support for creating global variables 79 | inside functions. As of this writing, global variables in bash are 80 | declared global by default only when using the simple declaration syntax 81 | but some variables like associative (not indexed) array variables that 82 | can only be created using the 'declare' builtin are always local if 83 | declared inside a function. 84 | 85 | Note: These limitations should not be applicable if you only intend to 86 | run the application in compiled form and not from the source scripts. 87 | 88 | 89 | Choosing a Shell Script Loader script 90 | 91 | Before it was recommended to always use the right implementation script 92 | for the shell for the sake of speed but it's now optional since the 93 | current implementation scripts are now capable of selecting optimized 94 | and/or proper functions for the running shell. 95 | 96 | For example, with loader.bash, associative arrays are automatically used 97 | if they can be used. Even with the generic script loader.sh, speed with 98 | the specialized versions does not really differ anymore. 99 | 100 | Please see the header notes of the implementation scripts to know what 101 | shells they support. You can also just use loader.sh to have 102 | compatibility with all shells that are compatible with the original sh 103 | with very little overhead. 104 | 105 | 106 | Loading the Script 107 | 108 | Implementation scripts of Shell Script Loader can be loaded just like 109 | any other shell script. In most shells, this can be done using '.' or 110 | 'source' targetting the implementation file. 111 | 112 | Also, arguments passed to an implementation script are not used and 113 | safely ignored but take note that these argument may replace the 114 | positional parameters. 115 | 116 | 117 | Functions 118 | 119 | (a) load() - Unconditionally loads a file even though it has already 120 | been flagged. 121 | 122 | usage: load 123 | load 124 | 125 | (b) include() - Also loads and flags a file like load() but only if the 126 | file has not yet been loaded with any of the three 127 | loading functions or flagged. 128 | 129 | usage: include 130 | include 131 | 132 | (c) call() - This function acts the same as load() but it loads the 133 | file in a separated environment or subshell. This is 134 | useful if a user wants to make a co-shell-script do its 135 | job without affecting the environment of the caller. 136 | The function also returns the exit code of the subshell 137 | after the subshell finishes executing. 138 | 139 | usage: call 140 | call 141 | 142 | (d) loader_addpath() - Accepts one or more arguments of directory paths 143 | and adds them to the list of searchable 144 | directories that will be used by load(), 145 | include() and call() when searching for files 146 | that are specified through partial paths. 147 | 148 | (e) loader_flag() - Marks the specified path to a file as if it's 149 | already been loaded with load(), include() or 150 | call(). Note that the file referred by path does 151 | not need to exist. 152 | 153 | This function is mostly useful like when you want 154 | to mark a loaded script that has not been loaded 155 | by any of the loading functions like the startup 156 | or main script that loads the implementation 157 | script. 158 | 159 | This function can accept any form of path (may it 160 | be absolute or relative) but note that the 161 | function always convert a path to its clean 162 | absolute form. 163 | 164 | usage: loader_flag 165 | 166 | (f) loader_reset() - This function behaves depending on the argument 167 | that is passed to it. 168 | 169 | usage: loader_reset [] 170 | 171 | flags - function will clear the flags 172 | paths - function will the list of search paths 173 | 174 | If no argument is passed, function will act on 175 | both items. If an unknown argument was passed, 176 | the function will generate a failure with an 177 | optional error message. 178 | 179 | (g) loader_finish() - Use this function to unload Shell Script Loader 180 | from shellspace. Everything except the variables 181 | LOADER_VERSION, LOADER_RS and LOADER_ACTIVE will 182 | be removed. 183 | 184 | Note: In the functions load() and include(), the co-shell-script is 185 | loaded inside the the same environment of the script along with the 186 | calling script's environment therefore if arguments are passed to the 187 | script upon load, replacement of the positional parameters with the 188 | arguments is expected. 189 | 190 | 191 | Reference Variables 192 | 193 | User scripts can also refer to some of the variables that an 194 | implementation script shall provide during load. This information can 195 | be used to check for compatibilies and to check if Shell Script Loader 196 | is still running or not. These variables will remain in shellspace even 197 | if loader_finish() was already called. 198 | 199 | (a) LOADER_VERSION - Refers to the version of the implementation script. 200 | 201 | (b) LOADER_RS - Refers to the version of Requiring Specification (RS) 202 | that is being implemented by the script. 203 | 204 | (c) LOADER_ACTIVE - This is set to 'true' if Shell Script Loader is 205 | already loaded and is still active (not yet removed 206 | with loader_finish()). The variable should be unset 207 | if Shell Script Loader was not yet loaded and set to 208 | 'false' if it is no longer active. 209 | 210 | 211 | Compilers 212 | 213 | Shell Script Loader was also designed so that the scripts that were 214 | created based from it can also be compiled to form a single script. 215 | 216 | As of this writing, a working compiler is already available. You can 217 | check the site where this program originally came for available 218 | compilers. 219 | 220 | 221 | Examples 222 | 223 | > . loader.sh 224 | > source ./loader.bash 225 | > source /usr/share/shellscript-loader/loader.zsh 226 | 227 | > loader_flag start.sh 228 | > loader_flag "${BASH_SOURCE[0]}" 229 | 230 | > loader_addpath source 231 | > loader_addpath /usr/share/scripts/sh 232 | 233 | > load main.sh 234 | > load some/reloadable.sh 235 | > include commands.sh 236 | > include utils/parawrap.sh 237 | > call checkconnection.sh && connected=true 238 | > call tools/strip.sh a.txt b.txt 239 | 240 | > loader_finish 241 | 242 | 243 | Prepared by konsolebox 244 | Copyright Free / Public Domain 245 | Aug. 29, 2009 (Last Updated 2011/04/07) 246 | -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/loader.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | 4 | # ---------------------------------------------------------------------- 5 | 6 | # loader.zsh 7 | # 8 | # This script implements Shell Script Loader for all versions of Zsh 9 | # starting 4.2. 10 | # 11 | # Please see loader.txt for more info on how to use this script. 12 | # 13 | # This script complies with the Requiring Specifications of 14 | # Shell Script Loader version 0 (RS0) 15 | # 16 | # Version: 0.1 17 | # 18 | # Author: konsolebox 19 | # Copyright Free / Public Domain 20 | # Aug. 29, 2009 (Last Updated 2011/04/07) 21 | 22 | # Notes: 23 | # 24 | # When using "typeset" or "declare" to declare global variables in 25 | # scripts, always add '-g' as an option. Not adding this option will 26 | # make the variables only have a local scope inside any of the functions 27 | # here that will be used to load the script. Among the major known 28 | # shells, only Zsh and Bash (ver. 4.2+) are the only shells that are 29 | # capable of having this explicit feature (as of this writing). There 30 | # are also other ways to declare global variables in other shells but 31 | # not through the use of "typeset" or "declare". Variables that can 32 | # only be declared using the two builtin commands sometimes can never be 33 | # declared global unless declared outside any function or the main 34 | # scope. 35 | # 36 | # This implementation script for Zsh actually is also tested to be 37 | # functionally compatible with versions 4.0.* and 4.1.* but these 38 | # earlier versions of Zsh have limited execution stack (job tables) that 39 | # are sometimes configured by default at small sizes and are also not 40 | # expandable unlike in 4.2.* and newer so I thought that it's better to 41 | # exclude these versions just to keep integrity. 42 | # 43 | # If you know what you're doing you may change the conditional 44 | # expression below to something like '[ ! "${ZSH_VERSION%%.*}" -ge 4 ]'. 45 | # You may want to do this for example, if you want your scripts to be 46 | # more compatible with most versions of Zsh and if you're sure that your 47 | # scripts doesn't make too much recursions in which even the earlier 48 | # versions will be able to handle. You may verify this by testing your 49 | # scripts with the earlier versions of Zsh that is configured to have 50 | # its limit set to minimum (see MAXJOB in zshconfig.ac). If you don't 51 | # find an error message like "job table full or recursion limit 52 | # exceeded", then as with respect to this issue, your scripts should 53 | # probably run just fine. 54 | 55 | # ---------------------------------------------------------------------- 56 | 57 | 58 | if [ "$LOADER_ACTIVE" = true ]; then 59 | echo "loader: loader cannot be loaded twice." 60 | exit 1 61 | fi 62 | if [ -z "$ZSH_VERSION" ]; then 63 | echo "loader: zsh is needed to run this script." 64 | exit 1 65 | fi 66 | if ! ( eval "set -- ${ZSH_VERSION//./ }"; [ "$1" -gt 4 ] || [ "$1" -eq 4 -a "$2" -ge 2 ]; exit "$?"; ); then 67 | echo "loader: only versions of zsh not earlier than 4.2.0 can work properly with this script." 68 | exit 1 69 | fi 70 | if [ "$ZSH_NAME" = sh -o "$ZSH_NAME" = ksh ]; then 71 | echo "loader: this script doesn't work if zsh is running in sh or ksh emulation mode." 72 | exit 1 73 | fi 74 | 75 | 76 | #### PUBLIC VARIABLES #### 77 | 78 | typeset -g LOADER_ACTIVE=true 79 | typeset -g LOADER_VERSION=0.1 80 | typeset -g LOADER_RS=0 81 | 82 | 83 | #### PRIVATE VARIABLES #### 84 | 85 | typeset -g -a LOADER_CS 86 | typeset -g -i LOADER_CS_I=0 87 | typeset -g -A LOADER_FLAGS 88 | typeset -g -a LOADER_PATHS 89 | typeset -g -A LOADER_PATHS_FLAGS 90 | 91 | 92 | #### PUBLIC FUNCTIONS #### 93 | 94 | function load { 95 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." load 96 | 97 | case "$1" in 98 | '') 99 | loader_fail "file expression cannot be null." load "$@" 100 | ;; 101 | /*|./*|../*) 102 | if [[ -f $1 ]]; then 103 | loader_getabspath "$1" 104 | 105 | [[ -r $__ ]] || loader_fail "file not readable: $__" load "$@" 106 | 107 | shift 108 | loader_load "$@" 109 | 110 | return 111 | fi 112 | ;; 113 | *) 114 | for __ in "${LOADER_PATHS[@]}"; do 115 | [[ -f $__/$1 ]] || continue 116 | 117 | loader_getabspath "$__/$1" 118 | 119 | [[ -r $__ ]] || loader_fail "found file not readable: $__" load "$@" 120 | 121 | LOADER_FLAGS[$1]=. 122 | 123 | shift 124 | loader_load "$@" 125 | 126 | return 127 | done 128 | ;; 129 | esac 130 | 131 | loader_fail "file not found: $1" load "$@" 132 | } 133 | 134 | function include { 135 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." include 136 | 137 | case "$1" in 138 | '') 139 | loader_fail "file expression cannot be null." include "$@" 140 | ;; 141 | /*|./*|../*) 142 | loader_getabspath "$1" 143 | 144 | [[ -n ${LOADER_FLAGS[$__]} ]] && \ 145 | return 146 | 147 | if [[ -f $__ ]]; then 148 | [[ -r $__ ]] || loader_fail "file not readable: $__" include "$@" 149 | 150 | shift 151 | loader_load "$@" 152 | 153 | return 154 | fi 155 | ;; 156 | *) 157 | [[ -n ${LOADER_FLAGS[$1]} ]] && \ 158 | return 159 | 160 | for __ in "${LOADER_PATHS[@]}"; do 161 | loader_getabspath "$__/$1" 162 | 163 | if [[ -n ${LOADER_FLAGS[$__]} ]]; then 164 | LOADER_FLAGS[$1]=. 165 | 166 | return 167 | elif [[ -f $__ ]]; then 168 | [[ -r $__ ]] || loader_fail "found file not readable: $__" include "$@" 169 | 170 | LOADER_FLAGS[$1]=. 171 | 172 | shift 173 | loader_load "$@" 174 | 175 | return 176 | fi 177 | done 178 | ;; 179 | esac 180 | 181 | loader_fail "file not found: $1" include "$@" 182 | } 183 | 184 | function call { 185 | [[ $# -eq 0 ]] && loader_fail "function called with no argument." call 186 | 187 | case "$1" in 188 | '') 189 | loader_fail "file expression cannot be null." call "$@" 190 | ;; 191 | /*|./*|../*) 192 | if [[ -f $1 ]]; then 193 | loader_getabspath "$1" 194 | 195 | [[ -r $__ ]] || loader_fail "file not readable: $__" call "$@" 196 | 197 | ( 198 | shift 199 | loader_load "$@" 200 | ) 201 | 202 | return 203 | fi 204 | ;; 205 | *) 206 | for __ in "${LOADER_PATHS[@]}"; do 207 | [[ -f $__/$1 ]] || continue 208 | 209 | loader_getabspath "$__/$1" 210 | 211 | [[ -r $__ ]] || loader_fail "found file not readable: $__" call "$@" 212 | 213 | ( 214 | LOADER_FLAGS[$1]=. 215 | 216 | shift 217 | loader_load "$@" 218 | ) 219 | 220 | return 221 | done 222 | ;; 223 | esac 224 | 225 | loader_fail "file not found: $1" call "$@" 226 | } 227 | 228 | function loader_addpath { 229 | for __ in "$@"; do 230 | [[ -d $__ ]] || loader_fail "directory not found: $__" loader_addpath "$@" 231 | [[ -x $__ ]] || loader_fail "directory not accessible: $__" loader_addpath "$@" 232 | [[ -r $__ ]] || loader_fail "directory not searchable: $__" loader_addpath "$@" 233 | 234 | loader_getabspath_ "$__/." 235 | 236 | if [[ -z ${LOADER_PATHS_FLAGS[$__]} ]]; then 237 | LOADER_PATHS[${#LOADER_PATHS[@]}+1]=$__ 238 | LOADER_PATHS_FLAGS[$__]=. 239 | fi 240 | done 241 | } 242 | 243 | function loader_flag { 244 | [[ $# -eq 1 ]] || loader_fail "function requires a single argument." loader_flag "$@" 245 | loader_getabspath "$1" 246 | LOADER_FLAGS[$__]=. 247 | } 248 | 249 | function loader_reset { 250 | if [[ $# -eq 0 ]]; then 251 | set -A LOADER_FLAGS 252 | set -A LOADER_PATHS 253 | set -A LOADER_PATHS_FLAGS 254 | elif [[ $1 = flags ]]; then 255 | set -A LOADER_FLAGS 256 | elif [[ $1 = paths ]]; then 257 | set -A LOADER_PATHS 258 | set -A LOADER_PATHS_FLAGS 259 | else 260 | loader_fail "invalid argument: $1" loader_reset "$@" 261 | fi 262 | } 263 | 264 | function loader_finish { 265 | LOADER_ACTIVE=false 266 | 267 | unset \ 268 | load \ 269 | include \ 270 | call \ 271 | loader_addpath \ 272 | loader_fail \ 273 | loader_finish \ 274 | loader_flag \ 275 | loader_getabspath \ 276 | loader_getabspath_ \ 277 | loader_load \ 278 | loader_load_ \ 279 | loader_reset \ 280 | LOADER_CS \ 281 | LOADER_CS_I \ 282 | LOADER_FLAGS \ 283 | LOADER_PATHS \ 284 | LOADER_PATHS_FLAGS 285 | } 286 | 287 | 288 | #### PRIVATE FUNCTIONS #### 289 | 290 | function loader_load { 291 | LOADER_FLAGS[$__]=. 292 | 293 | LOADER_CS[++LOADER_CS_I]=$__ 294 | 295 | loader_load_ "$@" 296 | 297 | __=$? 298 | LOADER_CS[LOADER_CS_I--]=() 299 | return "$__" 300 | } 301 | 302 | function loader_load_ { 303 | . "$__" 304 | } 305 | 306 | function loader_getabspath { 307 | case "$1" in 308 | .|'') 309 | case "$PWD" in 310 | /) 311 | __=/. 312 | ;; 313 | *) 314 | __=${PWD%/} 315 | ;; 316 | esac 317 | ;; 318 | ..|../*|*/..|*/../*|./*|*/.|*/./*|*//*) 319 | loader_getabspath_ "$1" 320 | ;; 321 | /*) 322 | __=$1 323 | ;; 324 | *) 325 | __=${PWD%/}/$1 326 | ;; 327 | esac 328 | } 329 | 330 | function loader_getabspath_ { 331 | local -a TOKENS; set -A TOKENS 332 | local -i I=0 333 | local IFS=/ T 334 | 335 | __=$1 336 | 337 | case "$1" in 338 | /*) 339 | set -- ${=1} 340 | ;; 341 | *) 342 | set -- ${=PWD} ${=1} 343 | ;; 344 | esac 345 | 346 | for T; do 347 | case "$T" in 348 | ..) 349 | [[ I -ne 0 ]] && TOKENS[I--]=() 350 | continue 351 | ;; 352 | .|'') 353 | continue 354 | ;; 355 | esac 356 | 357 | TOKENS[++I]=$T 358 | done 359 | 360 | case "$__" in 361 | */) 362 | [[ I -ne 0 ]] && __="/${TOKENS[*]}/" || __=/ 363 | ;; 364 | *) 365 | [[ I -ne 0 ]] && __="/${TOKENS[*]}" || __=/. 366 | ;; 367 | esac 368 | } 369 | 370 | function loader_fail { 371 | local MESSAGE=$1 FUNC=$2 A I 372 | shift 2 373 | 374 | { 375 | echo "loader: ${FUNC}(): ${MESSAGE}" 376 | echo 377 | 378 | echo " current scope:" 379 | if [[ LOADER_CS_I -gt 0 ]]; then 380 | echo " ${LOADER_CS[LOADER_CS_I]}" 381 | else 382 | echo " (main)" 383 | fi 384 | echo 385 | 386 | if [[ $# -gt 0 ]]; then 387 | echo " command:" 388 | echo -n " $FUNC" 389 | for A; do 390 | echo -n " $A" 391 | done 392 | echo 393 | echo 394 | fi 395 | 396 | if [[ LOADER_CS_I -gt 0 ]]; then 397 | echo " call stack:" 398 | echo " (main)" 399 | for A in "${LOADER_CS[@]}"; do 400 | echo " -> $A" 401 | done 402 | echo 403 | fi 404 | 405 | echo " search paths:" 406 | if [[ ${#LOADER_PATHS[@]} -gt 0 ]]; then 407 | for A in "${LOADER_PATHS[@]}"; do 408 | echo " $A" 409 | done 410 | else 411 | echo " (empty)" 412 | fi 413 | echo 414 | 415 | echo " working directory:" 416 | echo " $PWD" 417 | echo 418 | } >&2 419 | 420 | exit 1 421 | } 422 | -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/module.txt: -------------------------------------------------------------------------------- 1 | Some Benefits of Module Oriented Scripting 2 | ------------------------------------------ 3 | 4 | Early ancestors of Loader were originally only meant to 5 | make modularization possible in shell scripts through a 6 | custom function named use(); that which is now named 7 | include(). The purpose was to make shellscripts easier 8 | to handle and more arranged. 9 | 10 | When modularization was made possible, coding truly 11 | became a lot easier. Co-shellscripts became a lot easier 12 | to add and remove, dependencies are no longer difficult 13 | to handle, and more importantly, common codes became 14 | shared and no longer have to be repeated in many parts of 15 | the whole code and in future applications that might try 16 | to reuse it. 17 | 18 | In a shared code, bugs related to that code can be easily 19 | fixed in one shot unlike when its not shared where all of 20 | its instances should be located, analyzed and fixed at 21 | the same time. 22 | 23 | As for multi-scripts, they no longer appear confusing as 24 | to deciding which subscript has to be loaded first. The 25 | subscripts can also be dynamically (re)located anywhere 26 | in the filesystem. The main script no longer has to be 27 | updated everytime a new subscript is added. It can call 28 | for its dependencies just like other scripts and may only 29 | specify its direct dependencies and no longer the 30 | indirect ones. If all of the subscripts properly specify 31 | their dependencies, the requiring script no longer has to 32 | call them in proper order. 33 | 34 | On a properly crafted set of modularized scripts, the 35 | developer should easily recognize how the whole code 36 | works by just looking at its main code. Also, as related 37 | to bugs and features of a module script, a developer can 38 | easily fix or improve those without needing to touch the 39 | other scripts that depends on the script. 40 | 41 | konsolebox, 2009-08-29 42 | -------------------------------------------------------------------------------- /contrib/shellscriptloader-0.1.1/version.txt: -------------------------------------------------------------------------------- 1 | 0.1.1 -------------------------------------------------------------------------------- /packages/nvidia/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /packages/nvidia/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | BINPREFIX ?= $(PREFIX)/bin 3 | BUILDDIR ?= build 4 | 5 | CSCRIPT := ../../compile.sh 6 | CFLAGS += -O -a /home/jaagr/.local/lib/sh -s "'/usr/bin/env bash'" 7 | 8 | all: build 9 | 10 | build: 11 | mkdir -p -v $(BUILDDIR) 12 | for f in gpu-*; do \ 13 | $(CSCRIPT) $$f $(BUILDDIR)/$$f $(CFLAGS) ; \ 14 | done 15 | 16 | install: 17 | for f in gpu-*; do \ 18 | install -Dvm755 $(BUILDDIR)/$$f $(DESTDIR)$(BINPREFIX)/$$f ; \ 19 | done 20 | 21 | uninstall: 22 | for f in gpu-*; do \ 23 | rm -vf $(DESTDIR)$(BINPREFIX)/$$f ; \ 24 | done 25 | 26 | clean: 27 | rm -rf build 28 | 29 | .PHONY: build install uninstall clean 30 | 31 | # vim:ts=2 sw=2 noet nolist 32 | -------------------------------------------------------------------------------- /packages/nvidia/gpu-change: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/log.sh 6 | include utils/log/defer.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | local to_state 13 | 14 | if [[ "$1" == "on" ]]; then 15 | to_state=1 16 | elif [[ "$1" == "off" ]]; then 17 | to_state=0 18 | else 19 | log::err "Usage: ${0##*/} on|off"; exit 125 20 | fi 21 | 22 | if gpu-state; then 23 | if [[ $to_state -eq 1 ]]; then 24 | log::info "GPU state already ON..." ; exit 0 25 | fi 26 | elif [[ $to_state -eq 0 ]]; then 27 | log::info "GPU state already OFF..." ; exit 0 28 | fi 29 | 30 | if [[ $to_state -eq 1 ]]; then 31 | log::defer "Loading kernel modules..." 32 | err=$(sudo modprobe -a nvidia 2>&1 >/dev/null) 33 | lsmod | grep -q nvidia || { 34 | log::defer::failure "" "$err" ; exit 1 35 | } 36 | elif [[ $to_state -eq 0 ]]; then 37 | log::defer "Unloading kernel modules..." 38 | err=$(sudo modprobe -r nvidia 2>&1 >/dev/null) 39 | lsmod | grep -q nvidia && { 40 | log::defer::failure "" "$err" ; exit 1 41 | } 42 | 43 | log::defer "Sending new state to bbswitch..." 44 | sudo tee /proc/acpi/bbswitch <<< "OFF" >/dev/null 45 | fi 46 | 47 | log::defer "Verifying new GPU state..." 48 | 49 | if gpu-state; then 50 | if [[ $to_state -eq 1 ]]; then 51 | log::defer::success 52 | else 53 | log::defer::failure 54 | fi 55 | elif [[ $to_state -eq 0 ]]; then 56 | log::defer::success 57 | else 58 | log::defer::failure 59 | fi 60 | } 61 | 62 | main "$@" 63 | -------------------------------------------------------------------------------- /packages/nvidia/gpu-run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/log.sh 6 | include utils/log/defer.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | if [[ $# -lt 1 ]]; then 13 | log::err "Usage: ${0##*/} command"; exit 125 14 | fi 15 | 16 | log::info "Activating the GPU..." 17 | gpu-change on || exit 1 18 | 19 | trap 'gpu-state && { log::info "Deactivating the GPU..."; gpu-change off; }' 0 INT TERM 20 | 21 | log::info "Executing 'optirun $*'" 22 | optirun "$@" 2>&1 | while read -r line; do 23 | [[ "$line" ]] && log " $line" 24 | done 25 | } 26 | 27 | main "$@" 28 | -------------------------------------------------------------------------------- /packages/nvidia/gpu-state: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/log.sh 6 | include utils/log/defer.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | local gpu_loaded='true' 13 | 14 | lsmod | grep -q nvidia || exit 1 15 | 16 | bbswitch_status=$(&1 | grep -q 'direct rendering: Yes'; then 21 | log::defer::failure ; exit 22 | fi 23 | } 24 | 25 | main "$@" 26 | -------------------------------------------------------------------------------- /packages/sonybravia/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /packages/sonybravia/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | BINPREFIX ?= $(PREFIX)/bin 3 | SHRPREFIX ?= $(PREFIX)/share/sonybravia 4 | BUILDDIR ?= build 5 | 6 | CSCRIPT := ../../compile.sh 7 | CFLAGS += -O -a /home/jaagr/.local/lib/sh -s "'/usr/bin/env bash'" 8 | 9 | all: build 10 | 11 | build: 12 | mkdir -p -v $(BUILDDIR) 13 | for f in sonybravia-*; do \ 14 | cat $$f | sed '/#/!q' | tail -n+2 > $(BUILDDIR)/$$f.header ; \ 15 | $(CSCRIPT) $$f $(BUILDDIR)/$$f -H $(BUILDDIR)/$$f.header $(CFLAGS) ; \ 16 | done 17 | sed -i "s|commands.json|$(DESTDIR)$(SHRPREFIX)/commands.json|g" $(BUILDDIR)/sonybravia-ctl 18 | 19 | install: 20 | for f in sonybravia-*; do \ 21 | install -Dvm755 $(BUILDDIR)/$$f $(DESTDIR)$(BINPREFIX)/$$f ; \ 22 | done 23 | install -Dm755 commands.json $(DESTDIR)$(SHRPREFIX)/commands.json 24 | 25 | uninstall: 26 | for f in sonybravia-*; do \ 27 | rm -vf $(DESTDIR)$(BINPREFIX)/$$f ; \ 28 | done 29 | rm -vf $(DESTDIR)$(SHRPREFIX)/commands.json 30 | 31 | clean: 32 | rm -rf build 33 | 34 | .PHONY: build install uninstall clean 35 | 36 | # vim:ts=2 sw=2 noet nolist 37 | -------------------------------------------------------------------------------- /packages/sonybravia/commands.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 10, 3 | "result": [ 4 | { 5 | "bundled": true, 6 | "type": "RM-J1100" 7 | }, 8 | [ 9 | { 10 | "name": "PowerOff", 11 | "value": "AAAAAQAAAAEAAAAvAw==" 12 | }, 13 | { 14 | "name": "Input", 15 | "value": "AAAAAQAAAAEAAAAlAw==" 16 | }, 17 | { 18 | "name": "GGuide", 19 | "value": "AAAAAQAAAAEAAAAOAw==" 20 | }, 21 | { 22 | "name": "EPG", 23 | "value": "AAAAAgAAAKQAAABbAw==" 24 | }, 25 | { 26 | "name": "Favorites", 27 | "value": "AAAAAgAAAHcAAAB2Aw==" 28 | }, 29 | { 30 | "name": "Display", 31 | "value": "AAAAAQAAAAEAAAA6Aw==" 32 | }, 33 | { 34 | "name": "Home", 35 | "value": "AAAAAQAAAAEAAABgAw==" 36 | }, 37 | { 38 | "name": "Options", 39 | "value": "AAAAAgAAAJcAAAA2Aw==" 40 | }, 41 | { 42 | "name": "Return", 43 | "value": "AAAAAgAAAJcAAAAjAw==" 44 | }, 45 | { 46 | "name": "Up", 47 | "value": "AAAAAQAAAAEAAAB0Aw==" 48 | }, 49 | { 50 | "name": "Down", 51 | "value": "AAAAAQAAAAEAAAB1Aw==" 52 | }, 53 | { 54 | "name": "Right", 55 | "value": "AAAAAQAAAAEAAAAzAw==" 56 | }, 57 | { 58 | "name": "Left", 59 | "value": "AAAAAQAAAAEAAAA0Aw==" 60 | }, 61 | { 62 | "name": "Confirm", 63 | "value": "AAAAAQAAAAEAAABlAw==" 64 | }, 65 | { 66 | "name": "Red", 67 | "value": "AAAAAgAAAJcAAAAlAw==" 68 | }, 69 | { 70 | "name": "Green", 71 | "value": "AAAAAgAAAJcAAAAmAw==" 72 | }, 73 | { 74 | "name": "Yellow", 75 | "value": "AAAAAgAAAJcAAAAnAw==" 76 | }, 77 | { 78 | "name": "Blue", 79 | "value": "AAAAAgAAAJcAAAAkAw==" 80 | }, 81 | { 82 | "name": "Num1", 83 | "value": "AAAAAQAAAAEAAAAAAw==" 84 | }, 85 | { 86 | "name": "Num2", 87 | "value": "AAAAAQAAAAEAAAABAw==" 88 | }, 89 | { 90 | "name": "Num3", 91 | "value": "AAAAAQAAAAEAAAACAw==" 92 | }, 93 | { 94 | "name": "Num4", 95 | "value": "AAAAAQAAAAEAAAADAw==" 96 | }, 97 | { 98 | "name": "Num5", 99 | "value": "AAAAAQAAAAEAAAAEAw==" 100 | }, 101 | { 102 | "name": "Num6", 103 | "value": "AAAAAQAAAAEAAAAFAw==" 104 | }, 105 | { 106 | "name": "Num7", 107 | "value": "AAAAAQAAAAEAAAAGAw==" 108 | }, 109 | { 110 | "name": "Num8", 111 | "value": "AAAAAQAAAAEAAAAHAw==" 112 | }, 113 | { 114 | "name": "Num9", 115 | "value": "AAAAAQAAAAEAAAAIAw==" 116 | }, 117 | { 118 | "name": "Num0", 119 | "value": "AAAAAQAAAAEAAAAJAw==" 120 | }, 121 | { 122 | "name": "Num11", 123 | "value": "AAAAAQAAAAEAAAAKAw==" 124 | }, 125 | { 126 | "name": "Num12", 127 | "value": "AAAAAQAAAAEAAAALAw==" 128 | }, 129 | { 130 | "name": "VolumeUp", 131 | "value": "AAAAAQAAAAEAAAASAw==" 132 | }, 133 | { 134 | "name": "VolumeDown", 135 | "value": "AAAAAQAAAAEAAAATAw==" 136 | }, 137 | { 138 | "name": "Mute", 139 | "value": "AAAAAQAAAAEAAAAUAw==" 140 | }, 141 | { 142 | "name": "ChannelUp", 143 | "value": "AAAAAQAAAAEAAAAQAw==" 144 | }, 145 | { 146 | "name": "ChannelDown", 147 | "value": "AAAAAQAAAAEAAAARAw==" 148 | }, 149 | { 150 | "name": "SubTitle", 151 | "value": "AAAAAgAAAJcAAAAoAw==" 152 | }, 153 | { 154 | "name": "ClosedCaption", 155 | "value": "AAAAAgAAAKQAAAAQAw==" 156 | }, 157 | { 158 | "name": "Enter", 159 | "value": "AAAAAQAAAAEAAAALAw==" 160 | }, 161 | { 162 | "name": "DOT", 163 | "value": "AAAAAgAAAJcAAAAdAw==" 164 | }, 165 | { 166 | "name": "Analog", 167 | "value": "AAAAAgAAAHcAAAANAw==" 168 | }, 169 | { 170 | "name": "Teletext", 171 | "value": "AAAAAQAAAAEAAAA/Aw==" 172 | }, 173 | { 174 | "name": "Exit", 175 | "value": "AAAAAQAAAAEAAABjAw==" 176 | }, 177 | { 178 | "name": "Analog2", 179 | "value": "AAAAAQAAAAEAAAA4Aw==" 180 | }, 181 | { 182 | "name": "*AD", 183 | "value": "AAAAAgAAABoAAAA7Aw==" 184 | }, 185 | { 186 | "name": "Digital", 187 | "value": "AAAAAgAAAJcAAAAyAw==" 188 | }, 189 | { 190 | "name": "Analog?", 191 | "value": "AAAAAgAAAJcAAAAuAw==" 192 | }, 193 | { 194 | "name": "BS", 195 | "value": "AAAAAgAAAJcAAAAsAw==" 196 | }, 197 | { 198 | "name": "CS", 199 | "value": "AAAAAgAAAJcAAAArAw==" 200 | }, 201 | { 202 | "name": "BSCS", 203 | "value": "AAAAAgAAAJcAAAAQAw==" 204 | }, 205 | { 206 | "name": "Ddata", 207 | "value": "AAAAAgAAAJcAAAAVAw==" 208 | }, 209 | { 210 | "name": "PicOff", 211 | "value": "AAAAAQAAAAEAAAA+Aw==" 212 | }, 213 | { 214 | "name": "Tv_Radio", 215 | "value": "AAAAAgAAABoAAABXAw==" 216 | }, 217 | { 218 | "name": "Theater", 219 | "value": "AAAAAgAAAHcAAABgAw==" 220 | }, 221 | { 222 | "name": "SEN", 223 | "value": "AAAAAgAAABoAAAB9Aw==" 224 | }, 225 | { 226 | "name": "InternetWidgets", 227 | "value": "AAAAAgAAABoAAAB6Aw==" 228 | }, 229 | { 230 | "name": "InternetVideo", 231 | "value": "AAAAAgAAABoAAAB5Aw==" 232 | }, 233 | { 234 | "name": "Netflix", 235 | "value": "AAAAAgAAABoAAAB8Aw==" 236 | }, 237 | { 238 | "name": "SceneSelect", 239 | "value": "AAAAAgAAABoAAAB4Aw==" 240 | }, 241 | { 242 | "name": "Mode3D", 243 | "value": "AAAAAgAAAHcAAABNAw==" 244 | }, 245 | { 246 | "name": "iManual", 247 | "value": "AAAAAgAAABoAAAB7Aw==" 248 | }, 249 | { 250 | "name": "Audio", 251 | "value": "AAAAAQAAAAEAAAAXAw==" 252 | }, 253 | { 254 | "name": "Wide", 255 | "value": "AAAAAgAAAKQAAAA9Aw==" 256 | }, 257 | { 258 | "name": "Jump", 259 | "value": "AAAAAQAAAAEAAAA7Aw==" 260 | }, 261 | { 262 | "name": "PAP", 263 | "value": "AAAAAgAAAKQAAAB3Aw==" 264 | }, 265 | { 266 | "name": "MyEPG", 267 | "value": "AAAAAgAAAHcAAABrAw==" 268 | }, 269 | { 270 | "name": "ProgramDescription", 271 | "value": "AAAAAgAAAJcAAAAWAw==" 272 | }, 273 | { 274 | "name": "WriteChapter", 275 | "value": "AAAAAgAAAHcAAABsAw==" 276 | }, 277 | { 278 | "name": "TrackID", 279 | "value": "AAAAAgAAABoAAAB+Aw==" 280 | }, 281 | { 282 | "name": "TenKey", 283 | "value": "AAAAAgAAAJcAAAAMAw==" 284 | }, 285 | { 286 | "name": "AppliCast", 287 | "value": "AAAAAgAAABoAAABvAw==" 288 | }, 289 | { 290 | "name": "acTVila", 291 | "value": "AAAAAgAAABoAAAByAw==" 292 | }, 293 | { 294 | "name": "DeleteVideo", 295 | "value": "AAAAAgAAAHcAAAAfAw==" 296 | }, 297 | { 298 | "name": "PhotoFrame", 299 | "value": "AAAAAgAAABoAAABVAw==" 300 | }, 301 | { 302 | "name": "TvPause", 303 | "value": "AAAAAgAAABoAAABnAw==" 304 | }, 305 | { 306 | "name": "KeyPad", 307 | "value": "AAAAAgAAABoAAAB1Aw==" 308 | }, 309 | { 310 | "name": "Media", 311 | "value": "AAAAAgAAAJcAAAA4Aw==" 312 | }, 313 | { 314 | "name": "SyncMenu", 315 | "value": "AAAAAgAAABoAAABYAw==" 316 | }, 317 | { 318 | "name": "Forward", 319 | "value": "AAAAAgAAAJcAAAAcAw==" 320 | }, 321 | { 322 | "name": "Play", 323 | "value": "AAAAAgAAAJcAAAAaAw==" 324 | }, 325 | { 326 | "name": "Rewind", 327 | "value": "AAAAAgAAAJcAAAAbAw==" 328 | }, 329 | { 330 | "name": "Prev", 331 | "value": "AAAAAgAAAJcAAAA8Aw==" 332 | }, 333 | { 334 | "name": "Stop", 335 | "value": "AAAAAgAAAJcAAAAYAw==" 336 | }, 337 | { 338 | "name": "Next", 339 | "value": "AAAAAgAAAJcAAAA9Aw==" 340 | }, 341 | { 342 | "name": "Rec", 343 | "value": "AAAAAgAAAJcAAAAgAw==" 344 | }, 345 | { 346 | "name": "Pause", 347 | "value": "AAAAAgAAAJcAAAAZAw==" 348 | }, 349 | { 350 | "name": "Eject", 351 | "value": "AAAAAgAAAJcAAABIAw==" 352 | }, 353 | { 354 | "name": "FlashPlus", 355 | "value": "AAAAAgAAAJcAAAB4Aw==" 356 | }, 357 | { 358 | "name": "FlashMinus", 359 | "value": "AAAAAgAAAJcAAAB5Aw==" 360 | }, 361 | { 362 | "name": "TopMenu", 363 | "value": "AAAAAgAAABoAAABgAw==" 364 | }, 365 | { 366 | "name": "PopUpMenu", 367 | "value": "AAAAAgAAABoAAABhAw==" 368 | }, 369 | { 370 | "name": "RakurakuStart", 371 | "value": "AAAAAgAAAHcAAABqAw==" 372 | }, 373 | { 374 | "name": "OneTouchTimeRec", 375 | "value": "AAAAAgAAABoAAABkAw==" 376 | }, 377 | { 378 | "name": "OneTouchView", 379 | "value": "AAAAAgAAABoAAABlAw==" 380 | }, 381 | { 382 | "name": "OneTouchRec", 383 | "value": "AAAAAgAAABoAAABiAw==" 384 | }, 385 | { 386 | "name": "OneTouchStop", 387 | "value": "AAAAAgAAABoAAABjAw==" 388 | }, 389 | { 390 | "name": "DUX", 391 | "value": "AAAAAgAAABoAAABzAw==" 392 | }, 393 | { 394 | "name": "FootballMode", 395 | "value": "AAAAAgAAABoAAAB2Aw==" 396 | }, 397 | { 398 | "name": "Social", 399 | "value": "AAAAAgAAABoAAAB0Aw==" 400 | } 401 | ] 402 | ] 403 | } 404 | -------------------------------------------------------------------------------- /packages/sonybravia/sonybravia-ctl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Options: 4 | # -h, --help display this help and exit 5 | # -i, --ip=ADDRESSS sets the target ip address 6 | # -a, --auth authenticate with the device 7 | # -l, --list-commands show a list of available commands 8 | # 9 | # Interface for sending keycodes to my Sony Bravia TV 10 | # jaagr 11 | # 12 | 13 | source bootstrap.sh 14 | 15 | include utils/ansi.sh 16 | include utils/cli.sh 17 | include utils/log.sh 18 | include utils/log/defer.sh 19 | 20 | bootstrap::finish 21 | 22 | declare -r AUTH_COOKIE="${XDG_DATA_HOME}/sonybravia.cookie" 23 | 24 | function ensure_auth_cookie 25 | { 26 | log::defer "Looking for existing auth cookie" 27 | 28 | [[ -e "$AUTH_COOKIE" ]] || { 29 | log::defer::failure "" "No cookie found at $(ansi::bold "$AUTH_COOKIE")"; exit 1 30 | } 31 | 32 | log::defer::success 33 | } 34 | 35 | function translate_command 36 | { 37 | local command="$1" 38 | 39 | log::defer "Validating command $(ansi::bold "$command")" 40 | 41 | __COMMAND_KEYCODE=$(grep -i "\"$command\"" -A 1 "commands.json" | sed -nr '2s/.*:\s"(.*)"$/\1/p') 42 | 43 | [[ "$__COMMAND_KEYCODE" ]] || { 44 | log::defer::failure "" "Command not listed in commands.json"; exit 1 45 | } 46 | 47 | log::defer::success 48 | } 49 | 50 | function list_commands 51 | { 52 | log::info "List of available commands" 53 | sed -n -r 's/.*"(.+)",$/\1/p' "commands.json" | while read -r command; do 54 | log "- $command" 55 | done 56 | } 57 | 58 | function send_auth_request 59 | { 60 | local ip="$1" 61 | local payload response_code 62 | local nick device uuid 63 | local auth_header auth_code 64 | 65 | log::defer "Making sure we're not already authenticated" 66 | 67 | [[ -e "$AUTH_COOKIE" ]] && { 68 | log::defer::failure "" "An auth cookie is already present at $(ansi::bold "$AUTH_COOKIE"). Remove it to re-authenticate."; exit 1 69 | } 70 | 71 | log::defer::success 72 | 73 | nick=$(whoami) 74 | uuid=$(uuidgen) 75 | device=$(hostname) 76 | 77 | payload=$(printf '{"method":"actRegister","params":[{"clientid":"%s:%s","nickname":"%s","level":"private"},[{"value":"yes","function":"WOL"}]],"id":8,"version":"1.0"}"' "$nick" "$uuid" "$nick ($device)") 78 | 79 | log::defer "Sending authentication request" 80 | 81 | curl -s -XPOST "http://${ip}/sony/accessControl" -d "$payload" 82 | 83 | [[ $? -eq 0 ]] || { 84 | log::defer::failure "" "Failed with status code $?"; exit 1 85 | } 86 | 87 | log::defer::success 88 | 89 | log "Enter the 4-digit code shown on the TV: $(ansi::save_position)" 90 | ansi::restore_position 91 | read -r auth_code 92 | 93 | auth_header="Authorization: Basic $(printf ":%s" "$auth_code" | base64)" 94 | 95 | log::defer "Trying to authenticate using $(ansi::bold "$auth_code")" 96 | 97 | curl -s -i -XPOST "http://${ip}/sony/accessControl" -H "$auth_header" -d "$payload" | egrep -o 'auth=([a-z0-9]+)' > "$AUTH_COOKIE" 98 | 99 | [[ $? -eq 0 ]] || { 100 | log::defer::failure "" "Failed with status code $?"; exit 1 101 | } 102 | 103 | log::defer::success "Authentication successful" "Cookie stored at $(ansi::bold "$AUTH_COOKIE")" 104 | } 105 | 106 | function send_keycode 107 | { 108 | local addr="http://$1/sony/IRCC" 109 | local keycode="$2" 110 | local payload response_code 111 | 112 | keycode="${keycode//\"/}" 113 | keycode="${keycode//\'/}" 114 | 115 | read -r cookie < "$AUTH_COOKIE" 116 | 117 | log::defer "Sending keycode $(ansi::bold "$keycode") to $(ansi::bold "$addr")" 118 | 119 | payload="$keycode" 120 | response_code=$(curl -w '%{http_code}' -s -XPOST "$addr" -d "$payload" -H 'Content-Type: text/xml; charset=UTF-8' -H 'SOAPACTION: "urn:schemas-sony-com:service:IRCC:1#X_SendIRCC"' -H "Cookie: $cookie" -o /dev/null) 121 | 122 | [[ "$response_code" == "200" ]] || { 123 | log::defer::failure "" "Command failed with response_code ${response_code}"; exit 1 124 | } 125 | 126 | log::defer::success 127 | } 128 | 129 | function main 130 | { 131 | local ip='tv.local' 132 | local auth='false' 133 | 134 | while [[ "${1:0:1}" = "-" ]]; do 135 | case "$1" in 136 | "-h" | "--help") cli::usage_from_commentblock; exit;; 137 | "-i"* | "--ip"*) ip=$(cli::get_argument_value "$@") && shift ;; 138 | "-a" | "--auth") auth='true' ;; 139 | "-l" | "--list-commands") list_commands; exit ;; 140 | *) cli::unrecognized_option "$1" ;; 141 | esac 142 | shift 143 | done 144 | 145 | if $auth; then 146 | send_auth_request "$ip"; exit 147 | fi 148 | 149 | [[ $# -eq 0 ]] && { 150 | cli::usage_from_commentblock; exit 151 | } 152 | 153 | local command="$1" ; shift 154 | local n_events=1 155 | local keycode 156 | 157 | [[ $# -gt 0 ]] && { 158 | n_events=$(( command )) 159 | command="$1" 160 | } 161 | 162 | ensure_auth_cookie 163 | translate_command "$command" 164 | 165 | while (( n_events-- > 0 )); do 166 | send_keycode "$ip" "$__COMMAND_KEYCODE" 167 | done 168 | } 169 | 170 | main "$@" 171 | -------------------------------------------------------------------------------- /packages/sonybravia/sonybravia-remote: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/ansi.sh 6 | include utils/log.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | # forward if called with arguments 13 | if [[ $# -gt 0 ]]; then 14 | exec sonybravia-ctl "$@" 15 | fi 16 | 17 | declare -A commands 18 | 19 | commands[k]="up" 20 | commands[j]="down" 21 | commands[h]="left" 22 | commands[l]="right" 23 | commands[m]="mute" 24 | commands[return]="confirm" 25 | commands[backspace]="return" 26 | commands[+]="volumeup" 27 | commands[-]="volumedown" 28 | 29 | K_ESC=$(echo -e "\033") 30 | K_RETURN=$(echo -e "\n") 31 | K_BACKSPACE=$(tput kbs) 32 | 33 | ansi::save_position 34 | 35 | while read -r -N1 key; do 36 | ansi::clear_line 37 | ansi::restore_position 38 | 39 | if [[ "$key" == "$K_RETURN" ]]; then 40 | key="return" 41 | elif [[ "$key" == "$K_BACKSPACE" ]]; then 42 | key="backspace" 43 | fi 44 | 45 | if [[ "$key" == "$K_ESC" ]] || [[ "$key" == "q" ]]; then 46 | log "Exitting..." 47 | exit 48 | elif [[ "$key" ]] && [[ "${commands[$key]}" ]]; then 49 | log "${commands[$key]}" 50 | sonybravia-ctl "${commands[$key]}" >/dev/null 51 | else 52 | log::err "Key not mapped to a command" 53 | fi 54 | 55 | ansi::save_position 56 | done 57 | } 58 | 59 | main "$@" 60 | -------------------------------------------------------------------------------- /packages/themer/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /packages/themer/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | BINPREFIX ?= $(PREFIX)/bin 3 | ZSHCOMP ?= $(PREFIX)/share/zsh/site-functions 4 | BUILDDIR ?= build 5 | 6 | CSCRIPT := ../../compile.sh 7 | CFLAGS += -O -a /home/jaagr/.local/lib/sh -s "'/usr/bin/env bash'" 8 | 9 | all: build 10 | 11 | build: 12 | mkdir -p -v $(BUILDDIR) 13 | for f in theme-*; do \ 14 | $(CSCRIPT) $$f $(BUILDDIR)/$$f $(CFLAGS) ; \ 15 | done 16 | 17 | install: 18 | for f in theme-*; do \ 19 | install -Dvm755 $(BUILDDIR)/$$f $(DESTDIR)$(BINPREFIX)/$$f ; \ 20 | done 21 | install -Dm755 _themer $(DESTDIR)$(ZSHCOMP)/_themer 22 | 23 | uninstall: 24 | for f in theme-*; do \ 25 | rm -vf $(DESTDIR)$(BINPREFIX)/$$f ; \ 26 | done 27 | rm -vf $(DESTDIR)$(ZSHCOMP)/_themer 28 | 29 | clean: 30 | rm -rf build 31 | 32 | .PHONY: build install uninstall clean 33 | 34 | # vim:ts=2 sw=2 noet nolist 35 | -------------------------------------------------------------------------------- /packages/themer/_themer: -------------------------------------------------------------------------------- 1 | #compdef theme-activate theme-edit 2 | 3 | function _list_themes { 4 | compadd "$@" -- "$CURRENT_THEME"/../themes/*(:t) 5 | } 6 | 7 | function _list_current_configs { 8 | local -a files=("$CURRENT_THEME"/^README.md*(:t)) 9 | compadd "$@" -- ${files%%*.png} 10 | } 11 | 12 | case "$service" in 13 | theme-activate) 14 | _arguments : \ 15 | "(-h --help)"{-h,--help}"[display help]" \ 16 | "(-l --list)"{-l,--list}"[list themes]" \ 17 | "1:available themes:_list_themes" \ 18 | "*::" 19 | ;; 20 | theme-edit) 21 | _arguments : \ 22 | "(-h --help)"{-h,--help}"[display help]" \ 23 | "(-c --create)"{-c,--create}"[create configuration if it doesn't exist]" \ 24 | "1:current theme configurations:_list_current_configs" \ 25 | "*::" 26 | ;; 27 | esac 28 | -------------------------------------------------------------------------------- /packages/themer/theme-activate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Activates specified theme configuration 4 | # jaagr 5 | # 6 | 7 | source bootstrap.sh 8 | 9 | include utils/cli2.sh 10 | include utils/ansi.sh 11 | include utils/log.sh 12 | include utils/log/defer.sh 13 | 14 | bootstrap::finish 15 | 16 | cli::define_flag -h --help "Print this help text" 17 | cli::define_flag -l --list "List available themes" 18 | 19 | declare -r BASE_DIR="$LOCAL_ETC"/themer 20 | declare -r CURRENT_DIR="$BASE_DIR"/current 21 | 22 | function main 23 | { 24 | cli::parse "$@" 25 | 26 | if cli::flag --help; then 27 | cli::usage "[opts...] theme_name" ; exit 28 | elif cli::flag --list || [[ $# -eq 0 ]]; then 29 | local current_theme theme 30 | current_theme=$(dirname "$(readlink "$CURRENT_DIR"/*)" 2>/dev/null | tail -1 | xargs basename 2>/dev/null) 31 | 32 | log::info "Available themes:" 33 | 34 | for theme in "$BASE_DIR"/themes/*; do 35 | [[ -d "$theme" ]] || continue 36 | 37 | theme="${theme##*/}" 38 | 39 | if [[ "$theme" == "$current_theme" ]]; then 40 | log "$theme $(ansi::bold "(in use)")" 41 | else 42 | log "$theme" 43 | fi 44 | done 45 | 46 | exit 47 | fi 48 | 49 | local theme_name="$1" 50 | local theme_dir="${BASE_DIR}/themes/${theme_name}" 51 | local termite_config="${XDG_CONFIG_HOME}/termite/config" 52 | 53 | [[ "${theme_name}" ]] || { 54 | log::err "No theme given. Use '--list' to show available themes." ; exit 55 | } 56 | 57 | [[ -d "${theme_dir}" ]] || { 58 | log::err "Could not find theme '${theme_name}'. Show available themes with '--list'" ; exit 59 | } 60 | 61 | log::info "Applying theme $(ansi::bold "${theme_name}")" 62 | 63 | rm -f "${CURRENT_DIR}"/* &>/dev/null 64 | 65 | for file in "${theme_dir}"/*; do 66 | log::defer "Creating symlink to $(basename "${file}")" 67 | 68 | if ln -sf "${file}" "${CURRENT_DIR}/$(basename "${file}")"; then 69 | log::defer::success 70 | else 71 | log::defer::failure 72 | fi 73 | done 74 | 75 | [[ -e "${CURRENT_DIR}/termite" ]] && { 76 | if [[ -e "${termite_config}" ]]; then 77 | local termite_tag="themer::placeholder" 78 | 79 | if grep -q "${termite_tag}" "${termite_config}"; then 80 | log::defer "Creating backup of termite config" 81 | 82 | if ! cp "${termite_config}" "${termite_config}.bak"; then 83 | log::defer::failure "Failed with status $?" ; exit 1 84 | fi 85 | 86 | log::defer::success 87 | log::defer "Removing termite config" 88 | 89 | if ! rm "${termite_config}"; then 90 | log::defer::failure "Failed with status $?" ; exit 1 91 | fi 92 | 93 | log::defer::success 94 | 95 | line=$(sed -nr "/\[colors\]/q ; /font/=" "${termite_config}.bak" | tail -1) 96 | if grep -q "font" "${CURRENT_DIR}/termite" && [[ "${line}" ]] && [[ "$(grep "font" "${CURRENT_DIR}/termite")" != "$(sed -n "${line}p" "${termite_config}.bak")" ]]; then 97 | tmp=$(mktemp) 98 | log::info "Adding font to termite configuration" 99 | { 100 | sed "${line}q" "${termite_config}.bak" 101 | grep "font" "${CURRENT_DIR}/termite" 102 | sed "$((line+1))~1!d" "${termite_config}.bak" 103 | } > "${tmp}" 104 | mv "${tmp}" "${termite_config}.bak" 105 | fi 106 | 107 | log::info "Adding new colors to termite configuration" 108 | { 109 | sed "/${termite_tag}/q" "${termite_config}.bak" 110 | echo "# -- start of script output --" 111 | egrep -v "\[colors\]|font|^#" "${CURRENT_DIR}/termite" 112 | echo "# -- end of script output --" 113 | } >> "${termite_config}" 114 | else 115 | log::debug "Could not find placeholder in termite config" 116 | fi 117 | else 118 | log::debug "Could not find termite config file" 119 | fi 120 | } 121 | 122 | [[ -e ${CURRENT_DIR}/polybar ]] && [[ -e ${XDG_CONFIG_HOME}/polybar/.runargs ]] && { 123 | log::info "Removing cached runargs for polybar" 124 | rm -rf "${XDG_CONFIG_HOME}/polybar/.runargs" &>/dev/null 125 | } 126 | [[ -e ${CURRENT_DIR}/compton ]] && { 127 | log::info "Reloading compton" 128 | bash "${LOCAL_ETC}/compton/reload" &>/dev/null & 129 | } 130 | [[ -e ${CURRENT_DIR}/bspwm ]] && { 131 | log::info "Reloading bspwm" 132 | bash "${LOCAL_ETC}/bspwm/reload" &>/dev/null & 133 | } 134 | [[ -e ${CURRENT_DIR}/termite ]] && { 135 | log::info "Reloading termite" 136 | bash "${LOCAL_ETC}/termite/reload" &>/dev/null & 137 | } 138 | [[ -e ${CURRENT_DIR}/dunst ]] && { 139 | log::info "Reloading dunst" 140 | bash "${LOCAL_ETC}/dunst/reload" &>/dev/null & 141 | } 142 | [[ -e ${CURRENT_DIR}/wallpaper ]] && { 143 | log::info "Setting wallpaper" 144 | bash "${CURRENT_DIR}/wallpaper" &>/dev/null & 145 | } 146 | [[ -e ${CURRENT_DIR}/xresources ]] && { 147 | log::info "Applying xrdb overrides" 148 | xrdb -override "${CURRENT_DIR}/xresources" &>/dev/null & 149 | } 150 | 151 | log::ok "All done! Enjoy..." 152 | } 153 | 154 | main "$@" 155 | -------------------------------------------------------------------------------- /packages/themer/theme-edit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Opens up the specified theme config for edit 4 | # jaagr 5 | # 6 | 7 | source bootstrap.sh 8 | 9 | include utils/tests.sh 10 | include utils/cli2.sh 11 | include utils/ansi.sh 12 | include utils/log.sh 13 | include utils/log/defer.sh 14 | 15 | bootstrap::finish 16 | 17 | cli::define_flag -h --help "Print this help text" 18 | cli::define_flag -c --create "Create configuration if it doesn't exist" 19 | 20 | declare -r BASE_DIR="$LOCAL_ETC/themer" 21 | 22 | function main 23 | { 24 | cli::parse "$@" 25 | 26 | if cli::flag --help || [[ $# -eq 0 ]]; then 27 | cli::usage "[(current|theme_name).]" ; exit 28 | fi 29 | 30 | local theme_name 31 | local app_name 32 | local app_file 33 | 34 | if [[ "${1//[^.]/}" ]]; then 35 | theme_name="${1%%.*}" 36 | app_name="${1##*.}" 37 | else 38 | theme_name="current" 39 | app_name="$1" 40 | fi 41 | 42 | if ! [[ "$theme_name" ]] || ! [[ "$app_name" ]]; then 43 | cli::usage_from_commentblock; exit 44 | fi 45 | 46 | if [[ "$theme_name" == "current" ]]; then 47 | app_file="${BASE_DIR}/current/${app_name}" 48 | else 49 | app_file="${BASE_DIR}/themes/${theme_name}/${app_name}" 50 | fi 51 | 52 | if ! [[ -e "$app_file" ]]; then 53 | if ! cli::flag --create; then 54 | log::err "Could not find ${app_file}. Use --create to add the app file"; exit 55 | elif [[ "$theme_name" == "current" ]]; then 56 | log::err "Use a named theme when creating a new file"; exit 57 | fi 58 | fi 59 | 60 | log::info "Opening $app_file" 61 | vim "$app_file" 62 | log::ok "Done!" 63 | } 64 | 65 | main "$@" 66 | -------------------------------------------------------------------------------- /packages/x11/xmatch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Synopsis: 4 | # ${SCRIPT_NAME} [OPTION...] query 5 | # 6 | # Options: 7 | # -h, --help display this help and exit 8 | # -a, --atom=ATOM atom to match against 9 | # -w, --window=ID id of window to target 10 | # -p, --process match against pstree line instead (pstree -p | head -1) 11 | # -P, --process-root only match against process root 12 | # -x, --process-exact only match against process root 13 | # -i, --invert invert match 14 | # -v, --verbose output descriptive info 15 | # 16 | # Utility for matching X windows by atom value or pstree cmd string 17 | # jaagr 18 | # 19 | 20 | source bootstrap.sh 21 | 22 | include utils/ansi.sh 23 | include utils/cli.sh 24 | include utils/log.sh 25 | 26 | bootstrap::finish 27 | 28 | function main 29 | { 30 | local match='false' 31 | local verbose='false' 32 | local process='false' 33 | local process_root='false' 34 | local process_exact='false' 35 | local invert='false' 36 | local atom="WM_CLASS" 37 | local wid pid value query 38 | 39 | while [[ "${1:0:1}" = "-" ]]; do 40 | case "$1" in 41 | "-h" | "--help") cli::usage_from_commentblock; exit ;; 42 | "-v" | "--verbose") verbose='true' ;; 43 | "-a"*| "--atom"*) atom=$(cli::get_argument_value "$@") && shift ;; 44 | "-w"*| "--window"*) wid=$(cli::get_argument_value "$@") && shift ;; 45 | "-p" | "--process") process='true' ;; 46 | "-P" | "--process-root") process='true'; process_root='true' ;; 47 | "-x" | "--process-exact") process='true'; process_exact='true' ;; 48 | "-i" | "--invert") invert='true' ;; 49 | *) cli::unrecognized_option "$1" ;; 50 | esac 51 | shift 52 | done 53 | 54 | [[ $# -eq 0 ]] && { 55 | cli::usage_from_commentblock; exit 56 | } 57 | 58 | wid="$(xwid)" 59 | query="$*" 60 | 61 | if $process; then 62 | pid=$(( $(xprop -id "$wid" _NET_WM_PID | cut -d'=' -f2) )) 63 | value="$(pstree -p $pid | head -1)" 64 | else 65 | value="$(xprop -id "$wid" "$atom")" 66 | fi 67 | 68 | if $verbose; then 69 | if $invert; then 70 | log::info "Testing if window DOES NOT match user query" 71 | else 72 | log::info "Testing if window matches user query" 73 | fi 74 | 75 | log::info "Querying window $(ansi::bold "$wid")" 76 | log::debug "Using $(ansi::bold "$query") as query string" 77 | 78 | if $process; then 79 | log::debug "Matching against process id $(ansi::bold "$pid")" 80 | log::debug "Process command string $(ansi::bold "$value")" 81 | 82 | if $process_root; then 83 | log::debug "Only matches process root" 84 | fi 85 | 86 | if $process_exact; then 87 | log::debug "Requires exact match" 88 | fi 89 | else 90 | log::debug "Matching against atom $(ansi::bold "$atom")" 91 | log::debug "Atom value $(ansi::bold "$value")" 92 | fi 93 | fi 94 | 95 | if $process_exact; then 96 | sed -nr "/^$query$/q0 ; q1" <<< "$value" && match='true' 97 | elif $process_root; then 98 | sed -nr "/^$query\([0-9]+\)/q0 ; q1" <<< "$value" && match='true' 99 | elif $process; then 100 | sed -nr "/-$query\([0-9]+\)/q0 ; q1" <<< "$value" && match='true' 101 | elif [[ $value =~ $query ]]; then 102 | match='true' 103 | fi 104 | 105 | if $match && $invert; then 106 | match='false' 107 | fi 108 | 109 | if $verbose; then 110 | if $match; then 111 | log::ok "window matches" 112 | else 113 | log::err "window doesn't match" 114 | fi 115 | fi; 116 | 117 | $match || exit 1 118 | } 119 | 120 | main "$@" 121 | -------------------------------------------------------------------------------- /packages/x11/xwid: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function main 4 | { 5 | [[ $# -eq 0 ]] && \ 6 | set -- "echo" 7 | eval "$* $(xdo id)" 8 | } 9 | 10 | main "$@" 11 | -------------------------------------------------------------------------------- /packages/x11/xwincenter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [[ $# -eq 0 ]] && { 4 | echo "Usage: $(basename "$0") window_id"; exit 5 | } 6 | 7 | function main 8 | { 9 | local wid=$1 viewport display width height 10 | 11 | xdo id "$wid" &>/dev/null || { 12 | echo "Window does not exist" ; exit 1 13 | } 14 | 15 | viewport=$(lsw -r) 16 | display=$(xdo id -n root | head -1) 17 | width=$(wattr w "$display") 18 | width=$((width/2-$(wattr w "$wid")/2)) 19 | height=$(wattr h "$viewport"||echo 0) 20 | height=$((height - $(wattr h "$display") + $(wattr h "$display")/2)) 21 | 22 | wmv -a $width $height "$wid" 23 | } 24 | 25 | main "$@" 26 | -------------------------------------------------------------------------------- /packages/x11/xwindowname: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function print_title 4 | { 5 | [[ "$(bspc query -N -d)" ]] || { 6 | echo; return 7 | } 8 | 9 | xtitle -i 10 | } 11 | 12 | function main 13 | { 14 | if [[ "$1" = "tail" ]]; then 15 | bspc subscribe | while read -r evt; do 16 | print_title 17 | done 18 | else 19 | print_title 20 | fi 21 | } 22 | 23 | main "$@" 24 | -------------------------------------------------------------------------------- /packages/x11/xwinprocess: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [[ $# -eq 0 ]] && { 4 | echo "Usage: $(basename "$0") window_id"; exit 5 | } 6 | 7 | function main 8 | { 9 | local wid="$1" 10 | local pid 11 | 12 | pid=$(xprop -id "$1" _NET_WM_PID) 13 | pid=${pid##* } 14 | 15 | echo "$pid" 16 | ps -p "$pid" -h -o comm 17 | } 18 | 19 | main "$@" 20 | -------------------------------------------------------------------------------- /packages/x11/xwmstrut: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function main 4 | { 5 | if [[ $# -ne 5 ]]; then 6 | log::err "Usage: ${0##*/} bottom|top w h x y"; exit 125 7 | fi 8 | 9 | local pos="$1"; shift 10 | local h="$1"; shift 11 | local w="$1"; shift 12 | local x="$1"; shift 13 | local y="$1"; shift 14 | 15 | local top=0 16 | local top_start_x=0 17 | local top_end_x=0 18 | local bottom=0 19 | local bottom_start_x=0 20 | local bottom_end_x=0 21 | 22 | if [[ "$pos" == "bottom" ]]; then 23 | bottom=$((h+y)) 24 | bottom_start_x=$x 25 | bottom_end_x=$((x+w)) 26 | else 27 | top=$((h+y)) 28 | top_start_x=$x 29 | top_end_x=$((x+w)) 30 | fi 31 | 32 | xprop -f _NET_WM_STRUT_PARTIAL 32c -set _NET_WM_STRUT_PARTIAL \ 33 | "0, 0, ${top}, ${bottom}, 0, 0, 0, 0, ${top_start_x}, ${top_end_x}, ${bottom_start_x}, ${bottom_end_x}" 34 | } 35 | 36 | main "$@" 37 | -------------------------------------------------------------------------------- /standalone/encryptandsign: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Encrypt and sign given file 4 | # 5 | # Synopsis: 6 | # ${SCRIPT_NAME} [OPTION...] file 7 | # 8 | # Options: 9 | # -h, --help display this help and exit 10 | # -s, --sender=ID sender id 11 | # -r, --recipient=ID recipient id 12 | # 13 | 14 | source bootstrap.sh 15 | 16 | include utils/cli.sh 17 | include utils/log.sh 18 | 19 | bootstrap::finish 20 | 21 | function main 22 | { 23 | local file sender recipient abort=0 24 | 25 | [[ $# -eq 0 ]] && set -- "-h" 26 | 27 | while [[ "${1:0:1}" = "-" ]]; do 28 | case "$1" in 29 | "-h" | "--help") cli::usage_from_commentblock; exit;; 30 | "-s"*| "--sender"*) sender=$(cli::get_argument_value "$@") && shift ;; 31 | "-r"*| "--recipient"*) recipient=$(cli::get_argument_value "$@") && shift ;; 32 | *) cli::unrecognized_option "$1" ;; 33 | esac 34 | shift 35 | done 36 | 37 | file="$1" ; shift 38 | 39 | [[ "$sender" ]] || read -r -p "Sender: " sender 40 | [[ "$recipient" ]] || read -r -p "Recipient: " recipient 41 | [[ "$file" ]] || read -r -p "File: " file 42 | 43 | gpg --list-secret-keys "${sender}" &>/dev/null || { 44 | log::err "Unknown sender '${sender}'" ; abort=1 45 | } 46 | 47 | gpg --list-keys "${recipient}" &>/dev/null || { 48 | log::err "Unknown recipient '${recipient}'" ; abort=1 49 | } 50 | 51 | if ! [ -e "${file}" ]; then 52 | log::err "File '${file}' does not exist" ; abort=1 53 | elif ! [ -r "${file}" ]; then 54 | log::err "File '${file}' is not readable" ; abort=1 55 | fi 56 | 57 | [[ $abort -gt 0 ]] && { 58 | log::err "Prerequisites failed" ; exit 1 59 | } 60 | 61 | gpg --default-key "${sender}" --recipient "${recipient}" -e -s -a "${file}" "$@" 62 | } 63 | 64 | main "$@" 65 | -------------------------------------------------------------------------------- /standalone/lpassfind: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function main 4 | { 5 | if ! lpass status -q; then 6 | lpass login --trust "$(sudo cat /root/lpass_username)" >/dev/null || { 7 | echo "error: login failed"; exit 1 8 | } 9 | fi 10 | 11 | lpass show --clip --password "$(lpass ls | fzf | awk '{print $(NF)}' | sed 's/\]//g')" 12 | } 13 | 14 | main "$@" 15 | -------------------------------------------------------------------------------- /standalone/time_exec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/log.sh 6 | 7 | bootstrap::finish 8 | 9 | function main { 10 | local -i start seconds minutes 11 | 12 | log::info "Executing: $*" 13 | start=$(date +%s) 14 | eval "$@" 15 | 16 | let minutes=$(date +%s)-start seconds=minutes%60 minutes/=60 17 | log::info "Duration: ${minutes}m${seconds}s" 18 | } 19 | 20 | main "$@" 21 | -------------------------------------------------------------------------------- /standalone/timeout_prompt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # TODO: Replace the prompting with: 4 | # > select choice in OPT1 OPT2 OPT3 5 | 6 | require::set_timer(){ 7 | timeout="$1" ; shift 8 | 9 | [[ -n "$timeout_pid" ]] && kill "$timeout_pid" 10 | 11 | { sleep "$timeout" 12 | kill -SIGUSR1 0 13 | } & timeout_pid=$! 14 | } 15 | 16 | require::prompt(){ 17 | local text="$1" ; shift 18 | local choices=("$@") choice 19 | 20 | echo "Enter a valid choice (${choices[*]}):" 21 | read -r input 22 | 23 | [[ -n $timeout_pid ]] && kill "$timeout_pid" 24 | 25 | for choice in "${choices[@]}"; do 26 | if [[ "$input" == "$choice" ]]; then 27 | result="$choice"; return 28 | fi 29 | done 30 | 31 | [[ $input ]] && echo -e "\"$input\" is not a valid choice.\n" 32 | 33 | [[ -n "$timeout" ]] && require::set_timer "$timeout" 34 | 35 | require::prompt "$text" "${choices[@]}" 36 | } 37 | 38 | main() { 39 | trap 'return' SIGUSR1 40 | 41 | require::set_timer 3 42 | require::prompt "title" "A" "B" "C" 43 | 44 | if [[ -z "$result" ]]; then 45 | echo -e "Timeout"; exit 46 | fi 47 | 48 | echo "Result: $result" 49 | } 50 | 51 | main "$@" 2>/dev/null 52 | -------------------------------------------------------------------------------- /tpl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Lorem ipsum dolor sit amet... 4 | # jaagr 5 | # 6 | 7 | source bootstrap.sh 8 | 9 | include utils/log.sh 10 | include utils/cli2.sh 11 | 12 | bootstrap::finish 13 | 14 | cli::define_flag -h --help "Print this help text" 15 | cli::define_flag -f --force "..." 16 | 17 | function main { 18 | cli::parse "$@" 19 | 20 | if cli::flag --help; then 21 | cli::usage "[opts...] arg"; exit 22 | fi 23 | } 24 | 25 | main "$@" 26 | -------------------------------------------------------------------------------- /utils/_.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Set of functions used internally by the utils 4 | 5 | function _::stdout { 6 | echo "${FUNCNAME[1]} -> $*" 7 | } 8 | 9 | function _::stderr { 10 | echo "${FUNCNAME[1]} -> $*" >&2 11 | } 12 | 13 | function _::geom { 14 | echo "${1//[^0-9]/}x${2//[^0-9]/}+${3//[^0-9]/}+${4//[^0-9]/}" 15 | } 16 | -------------------------------------------------------------------------------- /utils/algo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function algo::luhn { 4 | local seq="$1" ; shift 5 | local val ret map i j 6 | 7 | for (( i=1 ; i<=${#seq} ; i+=1 )); do 8 | j="${seq:$i-1:1}" 9 | val=$(( j * ( i % 2 + 1 ) )); 10 | map="${map}${val}" 11 | done 12 | 13 | ret=$(echo "${map}" | sed -nr 's/(.)/\1+/gp' | sed -nr 's/^(.*)\+$/\1/gp' ) 14 | 15 | if [[ "${#seq}" -eq 9 ]]; then 16 | echo "$(( 10 - ( ret % 10 )))" 17 | else 18 | echo "$(( ret % 10 ))" 19 | fi 20 | } 21 | -------------------------------------------------------------------------------- /utils/alsa.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Alsa utility functions 4 | # jaagr 5 | # 6 | 7 | function alsa::get_card_index { 8 | amixer controls | sed -nr "s/^numid=([0-9]+).*CARD.*${1}.*/\1/p" 9 | } 10 | 11 | function alsa::is_connected { 12 | amixer cget "numid=$1" | sed -rn '$!d;/=on$/!q1' \ 13 | && return 0 \ 14 | || return 1 15 | } 16 | 17 | function alsa::get_volume { 18 | amixer sget "${1},0" | sed -nr 's/.*\[([0-9]+)%\].*/\1/p' 19 | } 20 | 21 | function alsa::set_volume { 22 | amixer -q set "${1},0" "${2}%" 23 | } 24 | 25 | function alsa::is_muted { 26 | amixer sget "${1},0" | sed -rn '$!d;/\[off\]$/!q1' \ 27 | && return 0 \ 28 | || return 1 29 | } 30 | 31 | function alsa::mute { 32 | local mixer="$1" ; shift 33 | local mode 34 | 35 | [[ $# -gt 0 ]] && mode=$1 || mode='true' 36 | 37 | if $mode; then 38 | amixer -q set "$mixer" off 39 | else 40 | amixer -q set "$mixer" on 41 | fi 42 | } 43 | 44 | function alsa::unmute { 45 | alsa::mute "$1" 'false' 46 | } 47 | -------------------------------------------------------------------------------- /utils/ansi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Utility functions for handling terminal output/formatting 4 | # jaagr 5 | # 6 | 7 | test '[post-pass:require-fn=ansi::check_support]' 8 | declare -gx __ANSI_SUPPORT='true' 9 | 10 | if ! [[ -t 1 ]]; then 11 | __ANSI_SUPPORT='false' 12 | fi 13 | test '[/post-pass:require-fn]' 14 | 15 | function ansi::check_support { 16 | $__ANSI_SUPPORT || [[ -t 1 ]] \ 17 | && return 0 \ 18 | || return 1 19 | } 20 | 21 | function ansi { 22 | if ansi::check_support; then 23 | printf "\033[%s" "$*" 24 | fi 25 | } 26 | 27 | function ansi::reset { 28 | ansi "0m" 29 | } 30 | 31 | function ansi::colorize { 32 | local colors=$1 ; shift 33 | ansi "${colors}m" 34 | printf "%s" "$*" 35 | ansi::reset 36 | } 37 | 38 | function ansi::bold { 39 | ansi "1m" 40 | printf "%s" "$*" 41 | ansi::reset 42 | } 43 | 44 | function ansi::italic { 45 | ansi "3m" 46 | printf "%s" "$*" 47 | ansi::reset 48 | } 49 | 50 | function ansi::conceal { 51 | ansi "8m" 52 | printf "%s" "$*" 53 | ansi::reset 54 | } 55 | 56 | function ansi::strikethrough { 57 | ansi "9m" 58 | printf "%s" "$*" 59 | ansi::reset 60 | } 61 | 62 | function ansi::beginning { 63 | printf "\r" 64 | } 65 | 66 | function ansi::up { 67 | ansi "${1}A" 68 | } 69 | 70 | function ansi::down { 71 | ansi "${1}B" 72 | } 73 | 74 | function ansi::left { 75 | ansi "${1}D" 76 | } 77 | 78 | function ansi::right { 79 | ansi "${1}C" 80 | } 81 | 82 | function ansi::line_up { 83 | ansi "${1}F" 84 | } 85 | 86 | function ansi::line_down { 87 | ansi "${1}E" 88 | } 89 | 90 | function ansi::move { 91 | local rows=$1 ; shift 92 | local cols=$1 ; shift 93 | 94 | if [[ $rows -lt 0 ]]; then 95 | ansi::up "${rows:1}" 96 | elif [[ $rows -gt 0 ]]; then 97 | ansi::down "$rows" 98 | fi 99 | 100 | if [[ $cols -lt 0 ]]; then 101 | ansi::left "${cols:1}" 102 | elif [[ $cols -gt 0 ]]; then 103 | ansi::right "$cols" 104 | fi 105 | } 106 | 107 | function ansi::move_absolute { 108 | local row=$1 ; shift 109 | local col=$1 ; shift 110 | ansi "${row};${col}f" 111 | } 112 | 113 | function ansi::save_position { 114 | ansi "s" 115 | } 116 | 117 | function ansi::restore_position { 118 | ansi "u" 119 | } 120 | 121 | function ansi::clear_screen { 122 | ansi::beginning 123 | ansi "2J" 124 | } 125 | 126 | function ansi::clear_lines_before { 127 | ansi::beginning 128 | ansi "1J" 129 | } 130 | 131 | function ansi::clear_lines_after { 132 | ansi::beginning 133 | ansi "0J" 134 | } 135 | 136 | function ansi::clear_line { 137 | ansi::beginning 138 | ansi "K" 139 | } 140 | 141 | function ansi::extend_buffer { 142 | if ansi::check_support; then 143 | printf "\n\n" 144 | ansi::line_up 2 145 | fi 146 | } 147 | 148 | #function ansi::is_last_line { 149 | # local report 150 | # report=$(ansi "6n") 151 | #} 152 | 153 | function ansi::draw_line { 154 | if ansi::check_support; then 155 | printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | sed -n -r "s/ /${1:-─}/gp" 156 | fi 157 | } 158 | -------------------------------------------------------------------------------- /utils/atexit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function sigaction { 4 | trap - INT TERM QUIT 0 5 | declare -f atexit >/dev/null && atexit 6 | } 7 | 8 | trap sigaction INT TERM QUIT 0 9 | -------------------------------------------------------------------------------- /utils/cli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Utility funtions for the cli 4 | # jaagr 5 | # 6 | 7 | include utils/log.sh 8 | 9 | function cli::usage_from_commentblock 10 | { 11 | [[ -n "$1" ]] && script="$1" || script="$0" 12 | 13 | local script_name 14 | script_name=$(basename "$script") 15 | 16 | local synopsis='false' 17 | local options='false' 18 | 19 | while read -r line 20 | do 21 | # Break at first non-comment line 22 | [[ "${line:0:1}" = '#' ]] || break 23 | 24 | [[ "${line##* }" == "Synopsis:" ]] && { 25 | synopsis='true' 26 | continue 27 | } 28 | [[ "${line##* }" == "Options:" ]] && { 29 | printf "\n" 30 | options='true' 31 | continue 32 | } 33 | 34 | if $synopsis; then 35 | line=${line:4} 36 | line=${line//\$\{SCRIPT_NAME\} /} 37 | line=${line//\$0 /} 38 | echo "Usage: $script_name $line" 39 | synopsis='false' 40 | continue 41 | fi 42 | 43 | if $options; then 44 | [[ "${line:0:4}" != "# " ]] && { 45 | printf "\n" 46 | options='false' 47 | continue 48 | } 49 | 50 | echo "${line:1}" 51 | fi 52 | done < "$script" 53 | } 54 | 55 | function cli::unrecognized_option 56 | { 57 | log::err "Unrecognized option '$1'" 58 | log "Try $(basename "$0") --help for more information." 59 | exit 125 60 | } 61 | 62 | function cli::get_argument_value 63 | { 64 | if [[ ${1:0:2} == "--" ]]; then 65 | echo "$1" | sed -rn 's/^--[^=\ ]*=([^\ ]*)$/\1/p' ; exit 1 66 | elif [[ ${#1} -eq 2 ]]; then 67 | echo "$2" ; exit 0 68 | else 69 | exit 1 70 | fi 71 | } 72 | -------------------------------------------------------------------------------- /utils/cli2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Utility funtions for the cli 4 | # jaagr 5 | # 6 | 7 | include utils/log.sh 8 | 9 | test '[post-pass:require-fn=cli::parse]' 10 | declare -gA __map=() 11 | declare -gA __revmap=() 12 | declare -gA __values=() 13 | declare -gA __flags=() 14 | declare -ga __positional=() 15 | 16 | declare -gi CLI_FLAG_NONE=1 17 | declare -gi CLI_FLAG_OPTVAL=2 18 | declare -gi CLI_FLAG_REQVAL=4 19 | test '[/post-pass:require-fn]' 20 | 21 | function cli::define_flag # (short,long,helptext) -> 22 | { 23 | local shortname="$1" ; shift 24 | local longname="$1" ; shift 25 | local helptext="$1" ; shift 26 | local -i flags=${1:-$CLI_FLAG_NONE} ; shift 27 | IFS="+" 28 | __map[$longname]="$flags+$shortname+$longname+${helptext//+/\\+}" 29 | __revmap[$shortname]=$longname 30 | } 31 | 32 | function cli::define_optflag 33 | { 34 | echo TODO 35 | } 36 | 37 | function cli::define_arg 38 | { 39 | echo TODO 40 | } 41 | 42 | function cli::define_optarg 43 | { 44 | echo TODO 45 | } 46 | 47 | function cli::flag 48 | { 49 | [[ "${__flags[$1]}" == "1" ]] 50 | } 51 | 52 | function cli::value 53 | { 54 | echo "${__values[$1]}" 55 | } 56 | 57 | function cli::get_positional 58 | { 59 | if [[ $# -eq 0 ]]; then 60 | echo "${__positional[@]}" 61 | elif [[ ${#__positional[@]} -ge $1 ]]; then 62 | echo "${__positional[$1]}" 63 | fi 64 | } 65 | 66 | function cli::parse 67 | { 68 | local -a map_entry 69 | local -i flags 70 | local value 71 | 72 | while [[ $# -gt 0 ]] 73 | do 74 | unset value 75 | 76 | if [[ ${1:0:1} != "-" ]]; then 77 | __positional+=("$1") 78 | shift 79 | continue 80 | elif [[ ${#__map[${1%%=*}]} -gt 0 ]]; then 81 | map_entry=(${__map[${1%%=*}][@]}) 82 | value="${1#*=}" 83 | if [[ ${#value} -eq ${#1} ]]; then 84 | unset value 85 | fi 86 | shiftcount=1 87 | 88 | elif [[ ${#__revmap[$1]} -gt 0 ]]; then 89 | map_entry=(${__map[${__revmap[$1]}][@]}) 90 | 91 | if [[ $# -gt 1 ]] && [[ ${2:0:1} != "-" ]]; then 92 | value="$2" 93 | shiftcount=2 94 | elif [[ $# -gt 1 ]] && [[ ${2:0:1} == "-" ]]; then 95 | shiftcount=1 96 | unset value 97 | fi 98 | 99 | else 100 | log::err "Unrecognized argument '$1'" ; exit 125 101 | fi 102 | 103 | local -n shortname="map_entry[1]" 104 | local -n longname="map_entry[2]" 105 | local -n flags_ref="map_entry[0]" 106 | 107 | let flags=$flags_ref 108 | 109 | if (( (flags & CLI_FLAG_NONE) == CLI_FLAG_NONE )); then 110 | if [[ "$value" ]] && [[ $shiftcount -gt 1 ]]; then 111 | let shiftcount--; 112 | unset value 113 | fi 114 | __flags[$longname]=1 115 | else 116 | 117 | if (( (flags & CLI_FLAG_REQVAL) == CLI_FLAG_REQVAL )) && ! [[ "$value" ]]; then 118 | log::err "Option '$longname' requires an argument..." ; exit 125 119 | fi 120 | 121 | if [[ ${#__values[$longname]} -gt 0 ]]; then 122 | log::err "Option '$longname' defined more than once..." ; exit 125 123 | fi 124 | 125 | __values[$longname]=$value 126 | fi 127 | 128 | shift $shiftcount 129 | done 130 | 131 | # for _ in "${!__values[@]}"; do 132 | # echo "$_ == ${__values[$_]}" 133 | # done 134 | 135 | # for _ in "${!__flags[@]}"; do 136 | # echo "$_ == ${__flags[$_]}" 137 | # done 138 | 139 | # for (( iter=0; iter<${#__positional[@]}; ++iter )); do 140 | # echo "${__positional[$iter]}" 141 | # done 142 | } 143 | 144 | function cli::usage 145 | { 146 | local -a map_entry 147 | local i maxlen=0 len=0 148 | 149 | for _ in "${!__map[@]}"; do 150 | map_entry=(${__map[$_][@]}) 151 | let len=${#map_entry[1]}+${#map_entry[2]} 152 | maxlen=$((len>maxlen?len:maxlen)) 153 | done 154 | let maxlen+=2 155 | 156 | printf "%s\n\n" "Usage: ${BASH_SOURCE[1]##*/} ${1:-[OPTION...]}" 157 | for _ in "${!__map[@]}"; do 158 | map_entry=(${__map[$_][@]}) 159 | printf " %s, %s" "${map_entry[1]}" "${map_entry[2]}" 160 | printf "%*s %s\n" $(( maxlen - ${#map_entry[1]} - ${#map_entry[2]} )) " " "${map_entry[3]}" 161 | done 162 | } 163 | 164 | function cli::usage_from_commentblock 165 | { 166 | [[ -n "$1" ]] && script="$1" || script="$0" 167 | 168 | local script_name 169 | script_name=$(basename "$script") 170 | 171 | local synopsis='false' 172 | local options='false' 173 | 174 | while read -r line 175 | do 176 | # Break at first non-comment line 177 | [[ "${line:0:1}" = '#' ]] || break 178 | 179 | [[ "${line##* }" == "Synopsis:" ]] && { 180 | synopsis='true' 181 | continue 182 | } 183 | [[ "${line##* }" == "Options:" ]] && { 184 | printf "\n" 185 | options='true' 186 | continue 187 | } 188 | 189 | if $synopsis; then 190 | line=${line:4} 191 | line=${line//\$\{SCRIPT_NAME\} /} 192 | line=${line//\$0 /} 193 | echo "Usage: $script_name $line" 194 | synopsis='false' 195 | continue 196 | fi 197 | 198 | if $options; then 199 | [[ "${line:0:4}" != "# " ]] && { 200 | printf "\n" 201 | options='false' 202 | continue 203 | } 204 | 205 | echo "${line:1}" 206 | fi 207 | done < "$script" 208 | } 209 | -------------------------------------------------------------------------------- /utils/color.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Utility funtions for colors 4 | # jaagr 5 | # 6 | 7 | include utils/math.sh 8 | include utils/log.sh 9 | 10 | function color::brightness { 11 | local hex=${1//[^[:xdigit:]]/}; shift 12 | local perc=$((100-$1)) 13 | 14 | [[ ${#hex} -eq 3 ]] && { 15 | hex="${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}" 16 | } 17 | 18 | [[ ${#hex} -ne 6 ]] && { 19 | log::err "Invalid hex color \"${hex}\""; return 1 20 | } 21 | 22 | local rgb str val i; 23 | 24 | for (( i=0 ; i<3 ; i+=1 )); do 25 | val="$(printf "%2f" "0x${hex:$((i*2)):2}")" 26 | val="$(math::float "${val}-(${perc}*(${val}/100))")" 27 | val="$(math::round "$val")" 28 | val="$(math::min "$val" 255)" 29 | val="$(math::max "$val" 0)" 30 | str="0$(printf "%x" "$val")" 31 | rgb="${rgb}${str:(-2)}" 32 | done 33 | 34 | echo "#${rgb}" 35 | } 36 | -------------------------------------------------------------------------------- /utils/json.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Utility funtions for json data 4 | # jaagr 5 | # 6 | 7 | function json::get_value { 8 | echo "$1" | jq ".$2" 9 | } 10 | -------------------------------------------------------------------------------- /utils/keycode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # shellcheck disable=SC2155 3 | # 4 | # Utility funtions for keyboard data 5 | # jaagr 6 | # 7 | 8 | test '[post-pass:require-fn=keycode::match_esc]' 9 | declare -r -g K_ESC="$(echo -ne "\033")" 10 | test '[/post-pass:require-fn]' 11 | test '[post-pass:require-fn=keycode::match_enter]' 12 | declare -r -g K_RETURN="$(echo -ne "\n")" 13 | test '[/post-pass:require-fn]' 14 | 15 | function keycode::is 16 | { 17 | local input="$1" ; shift 18 | 19 | typeset -n ref="$1" ; shift 20 | 21 | [[ "$input" == "$ref" ]] \ 22 | && return 0 \ 23 | || return 1 24 | } 25 | 26 | function keycode::match_esc { 27 | keycode::is "$1" K_ESC 28 | } 29 | function keycode::match_enter { 30 | keycode::is "$1" K_RETURN 31 | } 32 | -------------------------------------------------------------------------------- /utils/log.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | include utils/ansi.sh 4 | include utils/log/log.sh 5 | include utils/log/format/slim.sh 6 | -------------------------------------------------------------------------------- /utils/log/_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/ansi.sh 6 | include utils/log/banner.sh 7 | include utils/log/defer.sh 8 | 9 | function main { 10 | [[ $1 == "pending" || $# -eq 0 ]] && { 11 | echo -e "[utils/log/pending.sh]\n" 12 | 13 | log::defer "Pending..." ; sleep 0.25 14 | log::defer::success 15 | 16 | log::defer "Pending..." ; sleep 0.25 17 | log::defer::failure 18 | 19 | log::defer "Pending..." ; sleep 0.25 20 | log::defer::success "Success" "Lorem ipsum..." 21 | 22 | log::defer "Pending..." ; sleep 0.25 23 | log::defer::failure "Failure" "Lorem ipsum..." 24 | 25 | log::defer "Pending..." ; sleep 0.25 26 | log::defer::other "Replace message" 27 | } 28 | 29 | [[ $1 == "plain" || $# -eq 0 ]] && { 30 | [[ $# -eq 0 ]] && ansi::draw_line 31 | 32 | echo -e "[utils/log/format/plain.sh]\n" 33 | 34 | load utils/log/format/plain.sh 35 | 36 | log "Lorem ipsum dolor sit amet" 37 | log::debug "Lorem ipsum dolor sit amet" 38 | log::info "Lorem ipsum dolor sit amet" 39 | log::ok "Lorem ipsum dolor sit amet" 40 | log::warn "Lorem ipsum dolor sit amet" 41 | log::err "Lorem ipsum dolor sit amet" 42 | log::fatal "Lorem ipsum dolor sit amet" 43 | 44 | echo -e "\n[utils/log/pending.sh + utils/log/format/plain.sh]\n" 45 | 46 | log::defer "Pending..." ; sleep 0.25 47 | log::defer::success 48 | 49 | log::defer "Pending..." ; sleep 0.25 50 | log::defer::failure 51 | 52 | log::defer "Pending..." ; sleep 0.25 53 | log::defer::success "Success" "Lorem ipsum..." 54 | 55 | log::defer "Pending..." ; sleep 0.25 56 | log::defer::failure "Failure" "Lorem ipsum..." 57 | 58 | log::defer "Pending..." ; sleep 0.25 59 | log::defer::other "Replace message" 60 | } 61 | 62 | [[ $1 == "tags" || $# -eq 0 ]] && { 63 | [[ $# -eq 0 ]] && ansi::draw_line 64 | 65 | echo -e "[utils/log/format/tags.sh]\n" 66 | 67 | load utils/log/format/tags.sh 68 | 69 | log "Lorem ipsum dolor sit amet" 70 | log::debug "Lorem ipsum dolor sit amet" 71 | log::info "Lorem ipsum dolor sit amet" 72 | log::ok "Lorem ipsum dolor sit amet" 73 | log::warn "Lorem ipsum dolor sit amet" 74 | log::err "Lorem ipsum dolor sit amet" 75 | log::fatal "Lorem ipsum dolor sit amet" 76 | 77 | echo -e "\n[utils/log/format/pending.sh + utils/log/format/tags.sh]\n" 78 | 79 | log::defer "Pending..." ; sleep 0.25 80 | log::defer::success 81 | 82 | log::defer "Pending..." ; sleep 0.25 83 | log::defer::failure 84 | 85 | log::defer "Pending..." ; sleep 0.25 86 | log::defer::success "Success" "Lorem ipsum..." 87 | 88 | log::defer "Pending..." ; sleep 0.25 89 | log::defer::failure "Failure" "Lorem ipsum..." 90 | 91 | log::defer "Pending..." ; sleep 0.25 92 | log::defer::other "Message" 93 | } 94 | 95 | [[ $1 == "blocks" || $# -eq 0 ]] && { 96 | [[ $# -eq 0 ]] && ansi::draw_line 97 | 98 | echo -e "[utils/log/format/blocks.sh]\n" 99 | 100 | load utils/log/format/blocks.sh 101 | 102 | log "Lorem ipsum dolor sit amet" 103 | log::debug "Lorem ipsum dolor sit amet" 104 | log::info "Lorem ipsum dolor sit amet" 105 | log::ok "Lorem ipsum dolor sit amet" 106 | log::warn "Lorem ipsum dolor sit amet" 107 | log::err "Lorem ipsum dolor sit amet" 108 | log::fatal "Lorem ipsum dolor sit amet" 109 | 110 | echo -e "\n[utils/log/format/pending.sh + utils/log/format/blocks.sh]\n" 111 | 112 | log::defer "Pending..." ; sleep 0.25 113 | log::defer::success 114 | 115 | log::defer "Pending..." ; sleep 0.25 116 | log::defer::failure 117 | 118 | log::defer "Pending..." ; sleep 0.25 119 | log::defer::success "Success" "Lorem ipsum..." 120 | 121 | log::defer "Pending..." ; sleep 0.25 122 | log::defer::failure "Failure" "Lorem ipsum..." 123 | 124 | log::defer "Pending..." ; sleep 0.25 125 | log::defer::other "Message" 126 | } 127 | 128 | [[ $1 == "icons" || $# -eq 0 ]] && { 129 | [[ $# -eq 0 ]] && ansi::draw_line 130 | 131 | echo -e "[utils/log/format/icons.sh]\n" 132 | 133 | load utils/log/format/icons.sh 134 | 135 | log "Lorem ipsum dolor sit amet" 136 | log::debug "Lorem ipsum dolor sit amet" 137 | log::info "Lorem ipsum dolor sit amet" 138 | log::ok "Lorem ipsum dolor sit amet" 139 | log::warn "Lorem ipsum dolor sit amet" 140 | log::err "Lorem ipsum dolor sit amet" 141 | log::fatal "Lorem ipsum dolor sit amet" 142 | 143 | echo -e "\n[utils/log/format/pending.sh + utils/log/format/icons.sh]\n" 144 | 145 | log::defer "Pending..." ; sleep 0.25 146 | log::defer::success 147 | 148 | log::defer "Pending..." ; sleep 0.25 149 | log::defer::failure 150 | 151 | log::defer "Pending..." ; sleep 0.25 152 | log::defer::success "Success" "Lorem ipsum..." 153 | 154 | log::defer "Pending..." ; sleep 0.25 155 | log::defer::failure "Failure" "Lorem ipsum..." 156 | 157 | log::defer "Pending..." ; sleep 0.25 158 | log::defer::other "Message" 159 | } 160 | 161 | [[ $1 == "slim" || $# -eq 0 ]] && { 162 | [[ $# -eq 0 ]] && ansi::draw_line 163 | 164 | echo -e "[utils/log/format/slim.sh]\n" 165 | 166 | load utils/log/format/slim.sh 167 | 168 | log "Lorem ipsum dolor sit amet" 169 | log::debug "Lorem ipsum dolor sit amet" 170 | log::info "Lorem ipsum dolor sit amet" 171 | log::ok "Lorem ipsum dolor sit amet" 172 | log::warn "Lorem ipsum dolor sit amet" 173 | log::err "Lorem ipsum dolor sit amet" 174 | log::fatal "Lorem ipsum dolor sit amet" 175 | 176 | echo -e "\n[utils/log/format/pending.sh + utils/log/format/slim.sh]\n" 177 | 178 | log::defer "Pending..." ; sleep 0.25 179 | log::defer::success 180 | 181 | log::defer "Pending..." ; sleep 0.25 182 | log::defer::failure 183 | 184 | log::defer "Pending..." ; sleep 0.25 185 | log::defer::success "Success" "Lorem ipsum..." 186 | 187 | log::defer "Pending..." ; sleep 0.25 188 | log::defer::failure "Failure" "Lorem ipsum..." 189 | 190 | log::defer "Pending..." ; sleep 0.25 191 | log::defer::other "Message" 192 | } 193 | 194 | [[ $1 == "banner" || $# -eq 0 ]] && { 195 | [[ $# -eq 0 ]] && ansi::draw_line 196 | 197 | echo -e "[utils/log/banner.sh]\n" 198 | 199 | log::banner 13 "test odd 1"; echo 200 | log::banner 13 "test odd2"; echo 201 | log::banner 10 "test even1"; echo 202 | log::banner 10 "test even 2"; echo 203 | 204 | log::banner 30 " " "44;37;1" 205 | log::banner 30 "test" "44;37;1" 206 | log::banner 30 " " "44;37;1" 207 | } 208 | } 209 | 210 | main "$@" 211 | -------------------------------------------------------------------------------- /utils/log/banner.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # shellcheck disable=2155 4 | function log::banner 5 | { 6 | local spaces=$1 ; shift 7 | local msg="$1" ; shift 8 | local ansi_attrs="${1:-41;37;1}" 9 | local length="${#msg}" 10 | local padding=$(printf "%*s" $(( (spaces - length) / 2 ))) 11 | local diff=$(( ${#padding} * 2 + length - spaces )) 12 | 13 | if [[ ${diff:0:1} == "-" ]]; then 14 | diff=${diff:1} 15 | fi 16 | 17 | if [[ $diff -eq 1 ]]; then 18 | msg="$msg " 19 | elif [[ $diff -gt 1 ]]; then 20 | hdiff=$((diff/2)) 21 | echo $diff 22 | msg="$(printf "%*s" $hdiff " ")$msg$(printf "%*s" $hdiff " ")" 23 | fi 24 | 25 | echo -e "\033[${ansi_attrs}m${padding}${msg}${padding}\033[0m" 26 | } 27 | -------------------------------------------------------------------------------- /utils/log/defer.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | include utils/log.sh 4 | include utils/ansi.sh 5 | include utils/keycode.sh 6 | 7 | test '[post-pass:require-fn=log::defer]' 8 | declare -gx __LOG_PENDING=0 9 | declare -gx __LOG_PENDING_MSG 10 | test '[/post-pass:require-fn]' 11 | 12 | function log::defer 13 | { 14 | # assume success for last log since no error was reported 15 | log::defer::_finish_pending 16 | ansi::beginning 17 | printf "%s" "$(log "$@")" 18 | __LOG_PENDING_MSG="$*" 19 | __LOG_PENDING=1 20 | trap 'log::defer::_finish_pending' EXIT 21 | } 22 | 23 | function log::defer::_finish_pending 24 | { 25 | if [[ $__LOG_PENDING -eq 1 ]]; then 26 | log::defer::success 27 | fi 28 | } 29 | 30 | function log::defer::_describe 31 | { 32 | local color="$1" ; shift 33 | printf "%${__LOG_PENDING_PAD}s" 34 | [[ "$__LOG_FORMAT" == "tags" ]] && printf " " 35 | if ansi::check_support; then 36 | printf "\033[1;${color}m\U2570\U2500\U2500\U2578\033[0m %s\n" "$@" 37 | else 38 | printf "%s\n" "$@" 39 | fi 40 | } 41 | 42 | function log::defer::success 43 | { 44 | local msg=${1:-$__LOG_PENDING_MSG} ; shift 45 | ansi::beginning 46 | if [[ "$msg" ]]; then 47 | ansi::check_support && ansi::clear_line 48 | ansi::check_support || printf "\n" 49 | fi 50 | log::ok "$msg" 51 | [[ $# -gt 0 ]] && log::defer::_describe "32" "$@" 52 | __LOG_PENDING=0 53 | } 54 | 55 | function log::defer::failure 56 | { 57 | local msg=${1:-$__LOG_PENDING_MSG} ; shift 58 | ansi::beginning 59 | if [[ "$msg" ]]; then 60 | ansi::check_support && ansi::clear_line 61 | ansi::check_support || printf "\n" 62 | fi 63 | log::err "$msg" 64 | [[ $# -gt 0 ]] && 1>&2 log::defer::_describe "31" "$@" 65 | __LOG_PENDING=0 66 | } 67 | 68 | function log::defer::other 69 | { 70 | local msg=$1 ; shift 71 | ansi::beginning 72 | if [[ "$msg" ]]; then 73 | ansi::check_support && ansi::clear_line 74 | ansi::check_support || printf "\n" 75 | fi 76 | log "$msg" 77 | [[ $# -gt 0 ]] && log::defer::_describe "32" "$@" 78 | __LOG_PENDING=0 79 | } 80 | 81 | function log::defer::countdown 82 | { 83 | local -n retval=$1 ; shift 84 | local -i seconds=$1 ; shift 85 | local -i timer 86 | local key 87 | 88 | ansi::extend_buffer 89 | log::defer "$(ansi::save_position)" "${@//%s/0}" 90 | 91 | seconds+=1; 92 | 93 | while (( --seconds > 0 )); do 94 | ansi::restore_position 95 | 96 | echo "${@//%s/$seconds}" 97 | 98 | read -s -r -N1 -t 1 key 99 | timer=$? 100 | 101 | if [[ $seconds -eq 1 ]]; then 102 | retval=2 ; break 103 | elif keycode::match_esc "$key" || [[ "$key" == "q" ]]; then 104 | retval=1 ; break 105 | elif [[ $timer -ne 142 ]]; then 106 | retval=0 ; break 107 | fi 108 | done 109 | 110 | ansi::restore_position 111 | } 112 | 113 | function log::defer::cmd 114 | { 115 | local fail_with_details='true' 116 | local err 117 | 118 | if [[ "$1" == 'true' ]]; then 119 | fail_with_details='true'; shift 120 | elif [[ "$1" == 'false' ]]; then 121 | fail_with_details='false'; shift 122 | fi 123 | 124 | err=$(/bin/sh -c "$@" 2>&1 >/dev/null) 125 | 126 | if [[ -n "$err" ]]; then 127 | if $fail_with_details; then 128 | log::defer::failure "" "$err" 129 | else 130 | log::defer::failure 131 | fi 132 | return 1 133 | fi 134 | 135 | log::defer::success 136 | } 137 | -------------------------------------------------------------------------------- /utils/log/format/blocks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test '[post-pass:require-fn=log::_format]' 4 | declare -gx __LOG_FORMAT="blocks" 5 | declare -gx __LOG_TAG_FORMAT=1 6 | declare -gx __LOG_PENDING_PAD=5 7 | test '[/post-pass:require-fn]' 8 | 9 | function log::_format 10 | { 11 | local ansi=$1 ; shift 12 | local tag=$1 ; shift 13 | 14 | printf "\033[%sm%6s \033[0;1;37m \033[0m%s" "$ansi" "$tag" "$*" 15 | } 16 | 17 | function log::prefix::log { 18 | echo "log" 19 | } 20 | function log::prefix::debug { 21 | echo "debug" 22 | } 23 | function log::prefix::info { 24 | echo "info" 25 | } 26 | function log::prefix::ok { 27 | echo "ok" 28 | } 29 | function log::prefix::warn { 30 | echo "warn" 31 | } 32 | function log::prefix::err { 33 | echo "err" 34 | } 35 | function log::prefix::fatal { 36 | echo "fatal" 37 | } 38 | 39 | function log::format::log { 40 | echo "30;47" 41 | } 42 | function log::format::debug { 43 | echo "30;45" 44 | } 45 | function log::format::info { 46 | echo "30;46" 47 | } 48 | function log::format::ok { 49 | echo "30;42" 50 | } 51 | function log::format::warn { 52 | echo "30;43" 53 | } 54 | function log::format::err { 55 | echo "30;41" 56 | } 57 | function log::format::fatal { 58 | echo "30;41" 59 | } 60 | -------------------------------------------------------------------------------- /utils/log/format/icons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test '[post-pass:require-fn=log::_format]' 4 | declare -gx __LOG_FORMAT="icons" 5 | declare -gx __LOG_PENDING_PAD=0 6 | test '[/post-pass:require-fn]' 7 | 8 | function log::_format 9 | { 10 | local ansi=$1 ; shift 11 | local icon=$1 ; shift 12 | printf "\033[%sm%s\033[22;39m %s\033[0m" "$ansi" "$icon" "$*" 13 | } 14 | 15 | function log::format::log { 16 | echo "0" 17 | } 18 | function log::format::debug { 19 | echo "1;35" 20 | } 21 | function log::format::info { 22 | echo "1;36" 23 | } 24 | function log::format::ok { 25 | echo "1;32" 26 | } 27 | function log::format::warn { 28 | echo "1;33" 29 | } 30 | function log::format::err { 31 | echo "1;31" 32 | } 33 | function log::format::fatal { 34 | echo "1;31" 35 | } 36 | 37 | function log::prefix::log { 38 | echo "+" 39 | } 40 | function log::prefix::debug { 41 | echo "d" 42 | } 43 | function log::prefix::info { 44 | echo "i" 45 | } 46 | function log::prefix::ok { 47 | echo "✓" 48 | } 49 | function log::prefix::warn { 50 | echo "!" 51 | } 52 | function log::prefix::err { 53 | echo "✘" 54 | } 55 | function log::prefix::fatal { 56 | echo "✘" 57 | } 58 | -------------------------------------------------------------------------------- /utils/log/format/plain.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test '[post-pass:require-fn=log::_format]' 4 | declare -gx __LOG_FORMAT="plain" 5 | declare -gx __LOG_PENDING_PAD=0 6 | test '[/post-pass:require-fn]' 7 | 8 | function log::_format 9 | { 10 | local ansi=$1 ; shift 11 | shift 12 | printf "\033[%sm%s\033[0m" "$ansi" "$*" 13 | } 14 | 15 | function log::format::log { 16 | echo "0" 17 | } 18 | function log::format::debug { 19 | echo "1;35" 20 | } 21 | function log::format::info { 22 | echo "1;36" 23 | } 24 | function log::format::ok { 25 | echo "1;32" 26 | } 27 | function log::format::warn { 28 | echo "1;33" 29 | } 30 | function log::format::err { 31 | echo "1;31" 32 | } 33 | function log::format::fatal { 34 | echo "1;31" 35 | } 36 | 37 | function log::prefix::log { 38 | : 39 | } 40 | function log::prefix::debug { 41 | : 42 | } 43 | function log::prefix::info { 44 | : 45 | } 46 | function log::prefix::ok { 47 | : 48 | } 49 | function log::prefix::warn { 50 | : 51 | } 52 | function log::prefix::err { 53 | : 54 | } 55 | function log::prefix::fatal { 56 | : 57 | } 58 | -------------------------------------------------------------------------------- /utils/log/format/slim.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test '[post-pass:require-fn=log::_format]' 4 | declare -gx __LOG_FORMAT="slim" 5 | declare -gx __LOG_TAG_FORMAT=1 6 | declare -gx __LOG_PENDING_PAD=1 7 | test '[/post-pass:require-fn]' 8 | 9 | function log::_format 10 | { 11 | local ansi="$1"; shift 12 | local tag="$1"; shift 13 | printf "\033[%sm ┃\033[0m %s" "$ansi" "$*" 14 | } 15 | 16 | function log::format::log { 17 | echo "2;37" 18 | } 19 | function log::format::debug { 20 | echo "1;35" 21 | } 22 | function log::format::info { 23 | echo "1;36" 24 | } 25 | function log::format::ok { 26 | echo "1;32" 27 | } 28 | function log::format::warn { 29 | echo "1;33" 30 | } 31 | function log::format::err { 32 | echo "1;31" 33 | } 34 | function log::format::fatal { 35 | echo "1;31" 36 | } 37 | 38 | function log::prefix::log { 39 | : 40 | } 41 | function log::prefix::debug { 42 | : 43 | } 44 | function log::prefix::info { 45 | : 46 | } 47 | function log::prefix::ok { 48 | : 49 | } 50 | function log::prefix::warn { 51 | : 52 | } 53 | function log::prefix::err { 54 | : 55 | } 56 | function log::prefix::fatal { 57 | : 58 | } 59 | -------------------------------------------------------------------------------- /utils/log/format/tags.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test '[post-pass:require-fn=log::_format]' 4 | declare -gx __LOG_FORMAT="tags" 5 | declare -gx __LOG_TAG_FORMAT=1 6 | declare -gx __LOG_TAG_PAD=5 7 | declare -gx __LOG_PENDING_PAD=3 8 | test '[/post-pass:require-fn]' 9 | 10 | function log::_format 11 | { 12 | local ansi=$1 ; shift 13 | local tag=$1 ; shift 14 | 15 | if [[ "$__LOG_TAG_FORMAT" -eq 2 ]]; then 16 | printf "\033[%sm%*s** \033[0m%s" "$ansi" "$__LOG_TAG_PAD" "" "$*" 17 | else 18 | printf "\033[%sm%*s \033[0;1;37m** \033[0m%s" "$ansi" "$__LOG_TAG_PAD" "$tag" "$*" 19 | fi 20 | } 21 | 22 | function log::format::log { 23 | echo "2;37" 24 | } 25 | function log::format::debug { 26 | echo "1;35" 27 | } 28 | function log::format::info { 29 | echo "1;36" 30 | } 31 | function log::format::ok { 32 | echo "1;32" 33 | } 34 | function log::format::warn { 35 | echo "1;33" 36 | } 37 | function log::format::err { 38 | echo "1;31" 39 | } 40 | function log::format::fatal { 41 | echo "1;31" 42 | } 43 | 44 | function log::prefix::log { 45 | echo "log" 46 | } 47 | function log::prefix::debug { 48 | echo "debug" 49 | } 50 | function log::prefix::info { 51 | echo "info" 52 | } 53 | function log::prefix::ok { 54 | echo "ok" 55 | } 56 | function log::prefix::warn { 57 | echo "warn" 58 | } 59 | function log::prefix::err { 60 | echo "err" 61 | } 62 | function log::prefix::fatal { 63 | echo "fatal" 64 | } 65 | -------------------------------------------------------------------------------- /utils/log/log.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | include utils/ansi.sh 4 | 5 | function log::_format { 6 | shift 7 | shift 8 | printf "%s" "$*" 9 | } 10 | 11 | function log::debug { 12 | if ansi::check_support; then 13 | echo -e "$(log::_format "$(log::format::debug)" "$(log::prefix::debug)" "$@")" 14 | else 15 | echo "[debug] $*" 16 | fi 17 | } 18 | 19 | function log::info { 20 | if ansi::check_support; then 21 | echo -e "$(log::_format "$(log::format::info)" "$(log::prefix::info)" "$@")" 22 | else 23 | echo "[info] $*" 24 | fi 25 | } 26 | 27 | function log::ok { 28 | if ansi::check_support; then 29 | echo -e "$(log::_format "$(log::format::ok)" "$(log::prefix::ok)" "$@")" 30 | else 31 | echo "[ok] $*" 32 | fi 33 | } 34 | 35 | function log::warn { 36 | if ansi::check_support; then 37 | echo 1>&2 -e "$(log::_format "$(log::format::warn)" "$(log::prefix::warn)" "$@")" 38 | else 39 | echo "[warn] $*" 40 | fi 41 | } 42 | 43 | function log::err { 44 | if ansi::check_support; then 45 | echo 1>&2 -e "$(log::_format "$(log::format::err)" "$(log::prefix::err)" "$@")" 46 | else 47 | echo "[err] $*" 48 | fi 49 | } 50 | 51 | function log::fatal { 52 | if ansi::check_support; then 53 | echo 1>&2 -e "$(log::_format "$(log::format::fatal)" "$(log::prefix::fatal)" "$@")" 54 | else 55 | echo "[fatal] $*" 56 | fi 57 | } 58 | 59 | function log { 60 | if ansi::check_support; then 61 | echo -e "$(log::_format "$(log::format::log)" "$(log::prefix::log)" "$@")" 62 | else 63 | echo "$@" 64 | fi 65 | } 66 | 67 | function log::prompt { 68 | prompt="$(log "$@")" 69 | read -p "$prompt" -N 1 -r __LOG_PROMPT_VALUE 70 | } 71 | -------------------------------------------------------------------------------- /utils/math.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Math utility functions for 4 | # jaagr 5 | # 6 | 7 | function math::min { 8 | (( $(math::float "$1" .0) < $(math::float "$2" .0) )) && echo "$1" || echo "$2" 9 | } 10 | 11 | function math::max { 12 | (( $(math::float "$1" .0) > $(math::float "$2" .0) )) && echo "$1" || echo "$2" 13 | } 14 | 15 | function math::float { 16 | printf "%${2:-.2}f" "$(echo "$1" | bc -l)" 17 | } 18 | 19 | function math::round { 20 | printf "%1.0f" "$(math::float "$1")" 21 | } 22 | 23 | function math::percentage { 24 | local value="$1" 25 | local total="$2" 26 | local decimals="$3" 27 | math::float "$(echo "${value} / ${total} * 100.0" | bc -l)" "${decimals}" 28 | } 29 | 30 | function math::percentage_of { 31 | local percentage="$1" 32 | local value="$2" 33 | local decimals="$3" 34 | math::float "$(echo "${percentage} * ${value} / 100.0" | bc -l)" "${decimals}" 35 | } 36 | 37 | function math::percentage_to_hex { 38 | printf "%02X" "$(math::round "$1 / 100.0 * 255.0")" 39 | } 40 | 41 | function math::bytes { 42 | math::round "$(echo "$1" | sed 's/.*/\L\0/;s/t/Xg/;s/g/Xm/;s/m/Xk/;s/k/X/;s/b//;s/X/ *1024/g')" 43 | } 44 | -------------------------------------------------------------------------------- /utils/notification.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Interface for sending notifications using libnotify 4 | # jaagr 5 | # 6 | 7 | function notification::__send { 8 | local urgency="$1" ; shift 9 | /usr/bin/notify-send -u "$urgency" "$@" 10 | } 11 | 12 | function notification::low { 13 | notification::__send "low" "$@" 14 | } 15 | 16 | function notification::normal { 17 | notification::__send "normal" "$@" 18 | } 19 | 20 | function notification::critical { 21 | notification::__send "critical" "$@" 22 | } 23 | -------------------------------------------------------------------------------- /utils/pipe.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Utility functions for managing named pipes 4 | # jaagr 5 | # 6 | 7 | pipe="" 8 | 9 | trap 'pipe::close' EXIT 10 | 11 | # fd=3 12 | # eval "exec $fd<> $fifo" 13 | 14 | function pipe::open 15 | { 16 | [ -z "$pipe" ] && { 17 | pipe=$(mktemp -u); 18 | } 19 | [ -p "$pipe" ] || { 20 | mkfifo "$pipe" 21 | exec 3<> "$pipe" 22 | } 23 | } 24 | 25 | function pipe::close 26 | { 27 | [ -p "$pipe" ] && { 28 | rm "$pipe" 29 | exec 3>&- 30 | } 31 | } 32 | 33 | function pipe::push 34 | { 35 | pipe::open 36 | echo "$@" >&3 37 | } 38 | 39 | function pipe::peek 40 | { 41 | read -r "$1" <&3 42 | } 43 | 44 | function pipe::tail 45 | { 46 | while read -r line <&3; do 47 | if [[ "$line" == "EOF" ]]; then 48 | break; 49 | fi 50 | echo "$line" 51 | done 52 | } 53 | -------------------------------------------------------------------------------- /utils/polybar.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Polybar utility funtions 4 | # jaagr 5 | # 6 | 7 | include utils/_.sh 8 | 9 | function polybar::config_value 10 | { 11 | if [[ $# -lt 3 ]]; then 12 | _::stderr "parameters: config bar parameter [fallback]"; exit 1 13 | fi 14 | 15 | local config="$1"; shift 16 | local bar="$1"; shift 17 | local parameter="$1"; shift 18 | local fallback="$1" 19 | 20 | polybar "$bar" --config="$config" --dump="$parameter" 2>/dev/null || echo "$fallback" 21 | } 22 | 23 | function polybar::alignment 24 | { 25 | if [[ $# -lt 2 ]]; then 26 | _::stderr "parameters: config bar"; exit 1 27 | fi 28 | 29 | local config="$1"; shift 30 | local bar="$1"; shift 31 | 32 | if [[ "$(polybar::config_value "$config" "$bar" bottom)" == "true" ]]; then 33 | echo bottom 34 | else 35 | echo top 36 | fi 37 | } 38 | 39 | function polybar::wm_name 40 | { 41 | if [[ $# -lt 2 ]]; then 42 | _::stderr "parameters: config bar"; exit 1 43 | fi 44 | 45 | polybar "$2" --config="$1" --print-wmname 2>/dev/null 46 | } 47 | 48 | # shellcheck disable=2155 49 | function polybar::drawline 50 | { 51 | if [[ $# -lt 4 ]]; then 52 | _::stderr "parameters: config monitor bar color [offset_y=0] [height=1]"; return 1 53 | fi 54 | 55 | local config="$1"; shift 56 | local monitor="$1"; shift 57 | local bar="$1"; shift 58 | local color="$1"; shift 59 | local offset_y="${1:-0}" 60 | local height="${2:-1}" 61 | local align="$(polybar::alignment "$config" "$bar")" 62 | local wmname="$(polybar::wm_name "$config" "$bar")" 63 | local w=$(polybar::config_value "$config" "$bar" width 100%) 64 | local h=$(polybar::config_value "$config" "$bar" height 0) 65 | local x=$(polybar::config_value "$config" "$bar" offset-x 0) 66 | local y=$(polybar::config_value "$config" "$bar" offset-y 0) 67 | local bt=$(polybar::config_value "$config" "$bar" border-top 0) 68 | local bb=$(polybar::config_value "$config" "$bar" border-bottom 0) 69 | 70 | xdrawrect "$monitor" "$align" "$w" "$height" "$x" "$((h+y+bt+bb+offset_y))" "$color" "effectline-${monitor}-${align}" "$wmname" 71 | } 72 | -------------------------------------------------------------------------------- /utils/proc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Helper functions for running processes 4 | # jaagr 5 | # 6 | 7 | include utils/log/defer.sh 8 | include utils/spinner.sh 9 | 10 | function proc::wait 11 | { 12 | local pid="$1" ; shift 13 | local outbuf 14 | local -i num=0 15 | 16 | ansi::extend_buffer 17 | 18 | log::defer "${1:-waiting for pid} $(ansi::colorize "31" "$pid") $(ansi::save_position)" 19 | 20 | while [ -d "/proc/${pid}" ]; do 21 | ansi::restore_position 22 | 23 | spinner::get outbuf num "spin_11" 24 | 25 | echo -e "]──${outbuf} " 26 | 27 | sleep 0.15 28 | done 29 | 30 | ansi::restore_position 31 | 32 | log::defer::success "Process finished" 33 | } 34 | 35 | function proc::run_and_wait 36 | { 37 | "$SHELL" -c "$1" & 38 | proc::wait "$!" 39 | } 40 | -------------------------------------------------------------------------------- /utils/runit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | include utils/log.sh 4 | include utils/log/defer.sh 5 | include utils/pipe.sh 6 | 7 | # TODO: remove 8 | DEFAULT_RUNSVDIR_PREFIX=/var/service 9 | DEFAULT_CONTAINER_ROOT=/etc/sv 10 | 11 | function runit::test_user_container 12 | { 13 | log::defer "Checking if user container is running..." 14 | 15 | if ! sudo sv status "${DEFAULT_RUNSVDIR_PREFIX}/usercontainer-$(whoami)" >/dev/null 2>&1; then 16 | log::defer::failure; return 1 17 | fi 18 | 19 | log::defer::success 20 | } 21 | 22 | function runit::is_service 23 | { 24 | local service=$1 ; shift 25 | local svroot 26 | 27 | [[ $# -gt 0 ]] && { 28 | svroot=$service 29 | service=$1 30 | } 31 | 32 | [[ "$service" ]] || { 33 | log::err "Service not specified"; exit 1 34 | } 35 | 36 | [[ "$service" ]] && [[ -e "${svroot:-$DEFAULT_CONTAINER_ROOT}/${service}" ]] 37 | } 38 | 39 | function runit::validate 40 | { 41 | local service="$1" ; shift 42 | local svroot 43 | 44 | [[ $# -gt 0 ]] && { 45 | svroot=$service 46 | service=$1 47 | } 48 | 49 | runit::is_service "${svroot:-$DEFAULT_CONTAINER_ROOT}" "$service" || { 50 | log::err "Service \"${service}\" does not exist"; exit 2 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /utils/spinner.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Utility library for creating spinners 4 | # jaagr 5 | # 6 | 7 | # Style constants {{{ 8 | 9 | test '[post-pass:require-fn=spinner::get]' 10 | declare -g -r SPINNER_STYLE_DOTS_1=("⣷" "⣯" "⣟" "⡿" "⢿" "⣻" "⣽" "⣾") 11 | declare -g -r SPINNER_STYLE_DOTS_2=("⠁" "⠂" "⠄" "⡀" "⢀" "⠠" "⠐" "⠈") 12 | 13 | declare -g -r SPINNER_STYLE_SPIN_1=("←" "↖" "↑" "↗" "→" "↘" "↓" "↙") 14 | declare -g -r SPINNER_STYLE_SPIN_2=("b" "ᓂ" "q" "ᓄ") 15 | declare -g -r SPINNER_STYLE_SPIN_3=("d" "ᓇ" "p" "ᓀ") 16 | declare -g -r SPINNER_STYLE_SPIN_4=("|" "/" "—" "\\\\\\") 17 | declare -g -r SPINNER_STYLE_SPIN_5=("x" "+") 18 | declare -g -r SPINNER_STYLE_SPIN_6=("◰" "◳" "◲" "◱") 19 | declare -g -r SPINNER_STYLE_SPIN_7=("◴" "◷" "◶" "◵") 20 | declare -g -r SPINNER_STYLE_SPIN_8=("◐" "◓" "◑" "◒") 21 | declare -g -r SPINNER_STYLE_SPIN_9=("⠂" "⠄" "⠠" "⠐") 22 | declare -g -r SPINNER_STYLE_SPIN_10=("🕐" "🕑" "🕒" "🕓" "🕔" "🕕" "🕖" "🕗" "🕘" "🕙" "🕚" "🕛") 23 | declare -g -r SPINNER_STYLE_SPIN_11=("🌕" "🌔" "🌓" "🌒" "🌑" "🌘" "🌗" "🌖") 24 | 25 | declare -g -r SPINNER_STYLE_GROW_1=("|" "b" "O" "b") 26 | declare -g -r SPINNER_STYLE_GROW_2=("_" "o" "O" "o") 27 | declare -g -r SPINNER_STYLE_GROW_3=("." "o" "O" "@" "*" " ") 28 | declare -g -r SPINNER_STYLE_GROW_4=("▁" "▂" "▃" "▄" "▅" "▆" "▇" "█" "▇" "▆" "▅" "▄" "▃" "▂") 29 | declare -g -r SPINNER_STYLE_GROW_5=("▉" "▊" "▋" "▌" "▍" "▎" "▏" "▎" "▍" "▌" "▋" "▊" "▉") 30 | declare -g -r SPINNER_STYLE_GROW_6=(" " "▏" "▎" "▍" "▌" "▋" "▊" "▉" "▉" "█" "▉" "▊" "▋" "▌" "▍" "▎" "▏") 31 | 32 | declare -g -r SPINNER_STYLE_MISC_1=("d" "|" "b" "|") 33 | declare -g -r SPINNER_STYLE_MISC_2=("q" "|" "p" "|") 34 | declare -g -r SPINNER_STYLE_MISC_3=("ᓂ" "—" "ᓄ" "—") 35 | declare -g -r SPINNER_STYLE_MISC_4=("ᓇ" "—" "ᓀ" "—") 36 | test '[/post-pass:require-fn]' 37 | 38 | # }}} 39 | 40 | function spinner::get 41 | { 42 | # reference variables to names 43 | # passed in as arguments 44 | local -n output=$1 ; shift 45 | local -n index=$1 ; shift 46 | local -u -n style=SPINNER_STYLE_${1:-dots_1} ; shift 47 | 48 | output=${style[$((index % ${#style[@]}))]} 49 | index+=1 50 | } 51 | 52 | function spinner::print 53 | { 54 | local buffer 55 | spinner::get buffer "$1" "$2" 56 | echo "$buffer" 57 | } 58 | -------------------------------------------------------------------------------- /utils/str.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function str::unicode { 4 | printf "%b" "\u$1" 5 | } 6 | 7 | function str::upper { 8 | tr '[:lower:]' '[:upper:]' <<< "$@" 9 | } 10 | 11 | function str::lower { 12 | tr '[:upper:]' '[:lower:]' <<< "$@" 13 | } 14 | 15 | function str::trim { 16 | sed -r 's/^\s*(\S)|(\S*)\s*$/\1\2/g' <<< "$@" 17 | } 18 | 19 | function str::pad 20 | { 21 | local width="$1" ; shift 22 | local str="$1" ; shift 23 | printf "%*b" "$width" "$str" 24 | } 25 | 26 | function str::right { 27 | str::pad "$(tput cols)" "$@" 28 | } 29 | 30 | function str::center 31 | { 32 | local str cols rows 33 | str="$1" ; shift 34 | cols=$(tput cols) 35 | rows=$(tput lines) 36 | tput cup $(( rows / 2 )) $(( cols / 2 - ${#str} / 2 )) 37 | printf "%b" "${str}" 38 | } 39 | 40 | function str::shift_right 41 | { 42 | local -i width=$1 43 | local fill="${2:- }" 44 | local shift_str 45 | 46 | shift_str="$(printf "%*s" "$width" "$fill")" 47 | shift_str="${shift_str// /$fill}" 48 | 49 | while read -r line; do 50 | echo -e "${shift_str}${line}" 51 | done 52 | } 53 | -------------------------------------------------------------------------------- /utils/testkit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | include utils/log.sh 4 | include utils/log/defer.sh 5 | 6 | load utils/log/format/icons.sh 7 | 8 | export __LOG_TAG_PAD=3 9 | 10 | function testkit::equals 11 | { 12 | local input=$1 13 | local expected_result=$2 14 | local actual_result 15 | 16 | actual_result="$(eval "${input}" 2>/dev/null)" 17 | 18 | if [[ "${actual_result}" == "${expected_result}" ]]; then 19 | log::ok "${input} \e[2m=\e[0m ${expected_result}" 20 | else 21 | log::err "Test failed" 22 | echo -e "\e[2m Input\e[0m ${input}" 23 | echo -e "\e[2mExpected\e[0m ${expected_result}" 24 | echo -e "\e[2m Actual\e[0m ${actual_result}" 25 | fi 26 | } 27 | 28 | function testkit::match_strings 29 | { 30 | local str=$1 31 | local expected_str=$2 32 | 33 | if [[ "${str}" == "${expected_str}" ]]; then 34 | log::ok "${str} \e[2m=\e[0m matched the expected string" 35 | else 36 | log::err "Test failed" 37 | echo -e "\e[2mExpected\e[0m ${expected_str}" 38 | echo -e "\e[2mActual \e[0m ${str}" 39 | fi 40 | } 41 | -------------------------------------------------------------------------------- /utils/tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function is_root { 4 | [[ "$(id -u)" -eq "0" ]] 5 | } 6 | 7 | function previous_cmd_successful { 8 | [[ "$?" -eq "0" ]] 9 | } 10 | 11 | function in_array 12 | { 13 | for item in $2; do 14 | [[ "${item}" = "$1" ]] && return 0 15 | done 16 | return 1 17 | } 18 | -------------------------------------------------------------------------------- /utils/tests/algo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/algo.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | testkit::equals "algo::luhn 551001253" "6" 13 | testkit::equals "algo::luhn 6602020015" "0" 14 | } 15 | 16 | main "$@" 17 | -------------------------------------------------------------------------------- /utils/tests/ansi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/ansi.sh 7 | 8 | bootstrap::finish 9 | 10 | # force ansi support 11 | function ansi::check_support { 12 | return 0 13 | } 14 | 15 | function main 16 | { 17 | testkit::equals "ansi::colorize 31 foobar" "$(echo -ne "\033[31mfoobar\033[0m")" 18 | testkit::equals "ansi::colorize 31 foo bar" "$(echo -ne "\033[31mfoo bar\033[0m")" 19 | testkit::equals "ansi::bold foobar" "$(echo -ne "\033[1mfoobar\033[0m")" 20 | testkit::equals "ansi::bold foo bar" "$(echo -ne "\033[1mfoo bar\033[0m")" 21 | testkit::equals "ansi::italic foobar" "$(echo -ne "\033[3mfoobar\033[0m")" 22 | testkit::equals "ansi::italic foo bar" "$(echo -ne "\033[3mfoo bar\033[0m")" 23 | testkit::equals "ansi::conceal foobar" "$(echo -ne "\033[8mfoobar\033[0m")" 24 | testkit::equals "ansi::conceal foo bar" "$(echo -ne "\033[8mfoo bar\033[0m")" 25 | testkit::equals "ansi::strikethrough foobar" "$(echo -ne "\033[9mfoobar\033[0m")" 26 | testkit::equals "ansi::strikethrough foo bar" "$(echo -ne "\033[9mfoo bar\033[0m")" 27 | } 28 | 29 | main "$@" 30 | -------------------------------------------------------------------------------- /utils/tests/color.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/color.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | testkit::equals "color::brightness '#ffffff' 25" "#404040" 13 | testkit::equals "color::brightness '#ffffff' 100" "#ffffff" 14 | testkit::equals "color::brightness '#000000' 13" "#000000" 15 | testkit::equals "color::brightness '#f9213c' 100" "#f9213c" 16 | testkit::equals "color::brightness '#c89abd' 50" "#644d5e" 17 | testkit::equals "color::brightness '#000' 50" "#000000" 18 | testkit::equals "color::brightness '#pp' 50" "" 19 | } 20 | 21 | main "$@" 22 | -------------------------------------------------------------------------------- /utils/tests/json.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/json.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | json=$(cat <<-EOF 13 | { 14 | \"x\": { 15 | \"real\": 1844, 16 | \"fake\": -5 17 | }, 18 | \"y\": 547, 19 | \"width\": 677, 20 | \"height\": 504 21 | } 22 | EOF 23 | ) 24 | json=${json// /} 25 | testkit::equals "json::get_value \"$json\" \"x.fake\"" "-5" | tr -d '\\\n' 26 | echo 27 | testkit::equals "json::get_value \"$json\" \"width\"" "677" | tr -d '\\\n' 28 | echo 29 | } 30 | 31 | main "$@" 32 | -------------------------------------------------------------------------------- /utils/tests/math.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/math.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | testkit::equals "math::min 3 9" "3" 13 | testkit::equals "math::min 3.300 3.5" "3.300" 14 | 15 | testkit::equals "math::max 9 8" "9" 16 | testkit::equals "math::max 3.300 3.5" "3.5" 17 | 18 | testkit::equals "math::float '1 / 5'" "0.20" 19 | testkit::equals "math::float '1 / 5' 0.5" "0.20000" 20 | 21 | testkit::equals "math::round 1" "1" 22 | testkit::equals "math::round 3.25" "3" 23 | testkit::equals "math::round 5.893" "6" 24 | 25 | testkit::equals "math::percentage 3.25 50" "6.50" 26 | testkit::equals "math::percentage 25 100 .0" "25" 27 | 28 | testkit::equals "math::percentage_of 1 125 0.4" "1.2500" 29 | testkit::equals "math::percentage_of 80 10" "8.00" 30 | testkit::equals "math::percentage_of 120 10" "12.00" 31 | 32 | testkit::equals "math::percentage_to_hex 100" "FF" 33 | testkit::equals "math::percentage_to_hex 0" "00" 34 | } 35 | 36 | main "$@" 37 | -------------------------------------------------------------------------------- /utils/tests/pipe.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/pipe.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | pipe::open 13 | 14 | pipe::push "value1" 15 | pipe::push "value2" 16 | pipe::push "value3" 17 | 18 | testkit::equals "pipe::peek 'tmp'; echo \$tmp" "value1" 19 | testkit::equals "pipe::peek 'tmp'; echo \$tmp" "value2" 20 | 21 | pipe::close 22 | 23 | testkit::equals "pipe::peek 'tmp'; echo \$tmp" "" 24 | 25 | pipe::open 26 | 27 | pipe::push "tail1" 28 | pipe::push "tail2" 29 | pipe::push "tail3" 30 | pipe::push "EOF" 31 | 32 | testkit::equals "tmp=\$(pipe::tail); echo \$tmp" "tail1 tail2 tail3" 33 | 34 | pipe::close 35 | } 36 | 37 | main "$@" 38 | -------------------------------------------------------------------------------- /utils/tests/proc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/proc.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | proc::run_and_wait "sleep 3 ; echo" 13 | } 14 | 15 | main "$@" 16 | -------------------------------------------------------------------------------- /utils/tests/spinner.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/spinner.sh 7 | 8 | bootstrap::finish 9 | 10 | function test_name_ref_update 11 | { 12 | local a 13 | local -i b=0 14 | spinner::get a b misc_1 15 | echo "$a" 16 | } 17 | 18 | function test_name_ref_update2 19 | { 20 | local a 21 | local -i b=1 22 | spinner::get a b 23 | echo "$b" 24 | } 25 | 26 | function main 27 | { 28 | local -i frame=0 29 | 30 | # test that get() sets the output reference 31 | testkit::equals "test_name_ref_update" "d" 32 | 33 | # test that get() increments the index reference 34 | testkit::equals "test_name_ref_update2" "2" 35 | 36 | testkit::equals "spinner::print frame" "⣷" 37 | let frame++ # Fake the name ref update 38 | 39 | testkit::equals "spinner::print frame" "⣯" 40 | let frame++ # Fake the name ref update 41 | 42 | testkit::equals "spinner::print frame" "⣟" 43 | let frame++ # Fake the name ref update 44 | 45 | testkit::equals "spinner::print frame" "⡿" 46 | 47 | 48 | local buffer out 49 | 50 | let frame=0 51 | spinner::get out frame misc_2 q 52 | buffer+=$out 53 | 54 | let frame=4 55 | spinner::get out frame grow_3 56 | buffer+=$out 57 | 58 | testkit::match_strings "$buffer" "q*" 59 | } 60 | 61 | main "$@" 62 | -------------------------------------------------------------------------------- /utils/tests/str.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source bootstrap.sh 4 | 5 | include utils/testkit.sh 6 | include utils/str.sh 7 | 8 | bootstrap::finish 9 | 10 | function main 11 | { 12 | testkit::equals "str::upper abc" "ABC" 13 | testkit::equals "str::upper 178abbb%" "178ABBB%" 14 | 15 | testkit::equals "str::lower ABC" "abc" 16 | testkit::equals "str::lower 178ABBB%" "178abbb%" 17 | 18 | testkit::equals 'echo -e "1\n2" | str::shift_right 2' "$(echo -e " 1\n 2")" 19 | testkit::equals 'echo -e "1\n2\n3" | str::shift_right 3 "a"' "$(echo -e "aaa1\naaa2\naaa3")" 20 | } 21 | 22 | main "$@" 23 | -------------------------------------------------------------------------------- /utils/x11.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # x11 utility functions 4 | # jaagr 5 | 6 | function x11::monitor_connected { 7 | xrandr --query | grep -q "^$1 connected" || \ 8 | xrandr --query | grep -q "^${1//-/} connected" 9 | } 10 | 11 | function x11::monitor_geom { 12 | xrandr --query \ 13 | | egrep "^$1 (dis)?connected" \ 14 | | egrep -o "[0-9]+x[0-9]+\+[0-9]*\+[0-9]*" 15 | } 16 | 17 | function x11::wmname_win { 18 | 2>/dev/null xwininfo -name "$1" \ 19 | | sed -nr "/Window id/s/.*0x([[:xdigit:]]+).*/\1/p" \ 20 | | xargs -r printf "0x%8s\n" \ 21 | | tr " " "0" 22 | } 23 | 24 | function x11::root_win { 25 | 2>/dev/null xwininfo -root \ 26 | | sed -nr "/Window id/s/.*(0x[[:xdigit:]]+).*/\1/p" \ 27 | | xargs -r printf "0x%8s\n" \ 28 | | tr " " "0" 29 | } 30 | 31 | # In bspwm, the root window for the specified monitor 32 | # can be matched against a window with the same geometry 33 | # and WM_CLASS instance set to "root" 34 | function x11::root_win_bspwm { 35 | if x11::monitor_connected "$1"; then 36 | xwininfo -root -children \ 37 | | grep "root.*[bB]spwm" \ 38 | | grep "$(x11::monitor_geom "$1")" \ 39 | | sed -nr "s/^[ ]+ 0x([[:xdigit:]]+).*/\1/p" \ 40 | | xargs -r printf "0x%8s\n" \ 41 | | tr " " "0" 42 | fi 43 | } 44 | 45 | # In i3, the root window for the specified monitor 46 | # can be matched against the wm_name "[i3 con] output ${monitor}" 47 | function x11::root_win_i3 { 48 | if x11::monitor_connected "$1"; then 49 | x11::wmname_win "[i3 con] output $1" 50 | fi 51 | } 52 | --------------------------------------------------------------------------------