├── COPYRIGHT ├── LICENSE ├── README.md ├── base64 └── decode.functions ├── children.functions ├── commandLine.functions ├── compatibility.functions ├── configuration.functions ├── core.functions ├── dependency ├── check.functions ├── check │ ├── Alpine.functions │ ├── CentOS.functions │ ├── Cygwin.functions │ ├── Debian.functions │ ├── Fedora.functions │ ├── FreeBSD.functions │ ├── Homebrew.functions │ ├── MacOsXPkgsrc.functions │ ├── Mageia.functions │ ├── NetBSD.functions │ ├── OpenBSD.functions │ ├── RedHat.functions │ └── SuSE.functions ├── dependency.functions ├── languagePackageManagers.functions └── languagePackageManagers │ └── Ruby.functions ├── file.functions ├── functions.functions ├── init.functions ├── licences.snippet ├── path.functions ├── pipefail.functions ├── snippet.functions ├── temporaryFiles.functions ├── trap.functions ├── umask.functions ├── validate.functions └── variable ├── array.functions └── variable.functions /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Comment: Distribution Compilation Copyright and License 3 | Copyright: Copyright © 2014-2015, Raphael Cohn 4 | License: MIT 5 | The MIT License (MIT) 6 | . 7 | Copyright © 2014-2015, Raphael Cohn 8 | . 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | . 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | . 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | Comment: MIT license and copyright as applies to all files. 28 | License: MIT 29 | The MIT License (MIT) 30 | . 31 | Copyright © 2014-2015, Raphael Cohn 32 | . 33 | Permission is hereby granted, free of charge, to any person obtaining a copy 34 | of this software and associated documentation files (the "Software"), to deal 35 | in the Software without restriction, including without limitation the rights 36 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 37 | copies of the Software, and to permit persons to whom the Software is 38 | furnished to do so, subject to the following conditions: 39 | . 40 | The above copyright notice and this permission notice shall be included in all 41 | copies or substantial portions of the Software. 42 | . 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 48 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 49 | SOFTWARE. 50 | 51 | Files: * 52 | Copyright: Copyright © 2014-2015, Raphael Cohn 53 | License: MIT 54 | 55 | Files: pipefail.functions 56 | Copyright: Copyright © 2014-2015, Raphael Cohn 57 | Copyright © 2003-2005, Joe Halpin 58 | Comment: permissive licensed code in this file is from http://cfajohnson.com/shell/cus-faq-2.html#Q11 as documented in the file and is Copyright © 2003-2005, Joe Halpin . This code has been modified. MIT modifications to this code, and all other contents of the file are MIT licensed and Copyright © 2014-2015, Raphael Cohn . 59 | License: MIT and permissive 60 | It may be copied freely. Exceptions are noted in individual answers. 61 | . 62 | The answers given in this FAQ list are provided with the best intentions, but they may not be accurate for any particular shell/os. They may be completely wrong for any shell/os. If you don't test the answers, that's a bug in your procedures. 63 | . 64 | There are no guarantees for the answers or recommendations given in this document. In fact, I don't even claim to have tested any or all of them myself. Many of the answers here have been contributed by one or more regular participants in the newsgroup, who I believe to be competent (certainly more competent than I am), but THERE ARE NO GUARANTEES. 65 | . 66 | Did I really need to make that all uppercase? Hopefully not, but there are a lot of lawyers around with too much time on their hands, so I want to make it clear that THERE ARE NO GUARANTEES about the accuracy of answers in this FAQ list. This is, hopefully, an aid to people trying to learn shell programming, but it is NOT a supported product. You have to figure out for yourself whether or not the answers here work for what you're trying to do. 67 | . 68 | Under no circumstances will the maintainer of this FAQ list, or any contributors to it, be held liable for any mistakes in this document. If the answers work for you, well and good. If not, please tell me and I'll modify them appropriately so that this will be more useful. 69 | . 70 | If you don't agree to that, don't read any farther than this. Reading beyond this point indicates your agreement. 71 | . 72 | If you do test the answers and find a problem, please send email to the maintainer (see above), so it can be corrected, or (preferably) post a question to the newsgroup so it can be discussed and corrected if there's a problem. 73 | . 74 | A number of people have contributed to this FAQ, knowingly or unknowingly. Some of the answers were taken from previous postings in the group, and other people contributed questions and answers directly to the maintainer, which you are welcome to do as well. 75 | . 76 | Among the contributors is Heiner Steven, who also provided the momentum to get this FAQ list started. He maintains a web site about shell programming that has a lot of good stuff in it: http://www.shelldorado.com/ 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | LICENSE terms are documented in the COPYRIGHT file at the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 2 | -------------------------------------------------------------------------------- /base64/decode.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core temporaryFiles variable 6 | 7 | core_base64_decode_string() 8 | { 9 | local string="$1" 10 | local decodedFilePath="$2" 11 | local append="$3" 12 | local index62Character="$4" 13 | local index63Character="$5" 14 | shift 5 15 | 16 | local TMP_FILE 17 | core_temporaryFiles_newFileToRemoveOnExit 18 | printf '%s' "$string" >"$TMP_FILE" 19 | 20 | core_base64_decode_file "$TMP_FILE" "$decodedFilePath" "$append" "$index62Character" "$index63Character" 21 | 22 | # Otherwise we can run out of tmpfs space 23 | rm -f "$TMP_FILE" || true 24 | } 25 | 26 | core_base64_decode_file() 27 | { 28 | local encodedFilePath="$1" 29 | local decodedFilePath="$2" 30 | local append="$3" 31 | local index62Character="$4" 32 | local index63Character="$5" 33 | 34 | if core_compatibility_whichNoOutput openssl; then 35 | if core_variable_isTrue "$append"; then 36 | openssl enc -base64 -d -in "$encodedFilePath" >>"$decodedFilePath" 37 | else 38 | openssl enc -base64 -d -in "$encodedFilePath" >"$decodedFilePath" 39 | fi 40 | return 0 41 | fi 42 | 43 | if core_compatibility_whichNoOutput gbase64; then 44 | if core_variable_isTrue "$append"; then 45 | gbase64 -d "$encodedFilePath" >>"$decodedFilePath" 46 | else 47 | gbase64 -d "$encodedFilePath" >"$decodedFilePath" 48 | fi 49 | return 0 50 | fi 51 | 52 | # GNU base64 uses -d but BSD uses -D! 53 | # Other implementations, eg http://www.fourmilab.ch/webtools/base64/, use -d 54 | if core_compatibility_whichNoOutput base64; then 55 | local exitCode 56 | if core_variable_isTrue "$append"; then 57 | set +e 58 | base64 -D "$encodedFilePath" >>"$decodedFilePath" 2>/dev/null 59 | exitCode=$? 60 | set -e 61 | else 62 | set +e 63 | base64 -D "$encodedFilePath" >"$decodedFilePath" 2>/dev/null 64 | exitCode=$? 65 | set -e 66 | fi 67 | 68 | if [ $exitCode -eq 0 ]; then 69 | return 0 70 | fi 71 | 72 | if core_variable_isTrue "$append"; then 73 | set +e 74 | base64 -d "$encodedFilePath" >>"$decodedFilePath" 2>/dev/null 75 | exitCode=$? 76 | set -e 77 | else 78 | set +e 79 | base64 -d "$encodedFilePath" >"$decodedFilePath" 2>/dev/null 80 | exitCode=$? 81 | set -e 82 | fi 83 | 84 | if [ $exitCode -eq 0 ]; then 85 | return 0 86 | fi 87 | 88 | core_message WARN "We don't recognise your 'base64' binary (or data is corrupt); use fallbacks" 89 | fi 90 | 91 | if core_compatibility_whichNoOutput fold; then 92 | if core_variable_isTrue "$append"; then 93 | _core_base64_decode_file "$@" _core_base64_decode_file_fold >>"$decodedFilePath" 94 | else 95 | _core_base64_decode_file "$@" _core_base64_decode_file_fold >"$decodedFilePath" 96 | fi 97 | return 0 98 | fi 99 | 100 | if core_compatibility_whichNoOutput awk; then 101 | if core_variable_isTrue "$append"; then 102 | _core_base64_decode_file "$@" _core_base64_decode_file_awk >>"$decodedFilePath" 103 | else 104 | _core_base64_decode_file "$@" _core_base64_decode_file_awk >"$decodedFilePath" 105 | fi 106 | return 0 107 | fi 108 | 109 | core_exitError $core_commandLine_exitCode_OSFILE "No utility to decode base64 found (openssl, gbase64, base64, fold, awk)" 110 | } 111 | 112 | _core_base64_decode_file_fold() 113 | { 114 | fold -b -w 1 "$encodedFilePath" 115 | } 116 | 117 | _core_base64_decode_file_awk() 118 | { 119 | awk '{for(i=1;i<=length;i++) print substr($0, i, 1)}' "$encodedFilePath" 120 | } 121 | 122 | _core_base64_decode_file() 123 | { 124 | local index62Character="$1" 125 | local index63Character="$2" 126 | local singleByteLineMethod="$3" 127 | 128 | local carriageReturn="$(printf '\r')" 129 | 130 | local accumulatedValue 131 | local value 132 | local valueShift 133 | local character 134 | accumulatedValue=0 135 | valueShift=18 136 | local equalsCount=0 137 | # || tries to deal with a final line not \n terminated 138 | $singleByteLineMethod | while IFS='' read -r character || [ -n "$character" ] 139 | do 140 | if [ -z "$character" ]; then 141 | continue 142 | fi 143 | 144 | if [ $equalsCount -eq 2 ]; then 145 | core_exitError $core_commandLine_exitCode_DATAERR "'=' embedded in base64-encoded data, not at end" 146 | fi 147 | 148 | case "$character" in 149 | 150 | "$carriageReturn") 151 | continue 152 | ;; 153 | 154 | A) 155 | value=0 156 | ;; 157 | 158 | B) 159 | value=1 160 | ;; 161 | 162 | C) 163 | value=2 164 | ;; 165 | 166 | D) 167 | value=3 168 | ;; 169 | 170 | E) 171 | value=4 172 | ;; 173 | 174 | F) 175 | value=5 176 | ;; 177 | 178 | G) 179 | value=6 180 | ;; 181 | 182 | H) 183 | value=7 184 | ;; 185 | 186 | I) 187 | value=8 188 | ;; 189 | 190 | J) 191 | value=9 192 | ;; 193 | 194 | K) 195 | value=10 196 | ;; 197 | 198 | L) 199 | value=11 200 | ;; 201 | 202 | M) 203 | value=12 204 | ;; 205 | 206 | N) 207 | value=13 208 | ;; 209 | 210 | O) 211 | value=14 212 | ;; 213 | 214 | P) 215 | value=15 216 | ;; 217 | 218 | Q) 219 | value=16 220 | ;; 221 | 222 | R) 223 | value=17 224 | ;; 225 | 226 | S) 227 | value=18 228 | ;; 229 | 230 | T) 231 | value=19 232 | ;; 233 | 234 | U) 235 | value=20 236 | ;; 237 | 238 | V) 239 | value=21 240 | ;; 241 | 242 | W) 243 | value=22 244 | ;; 245 | 246 | X) 247 | value=23 248 | ;; 249 | 250 | Y) 251 | value=24 252 | ;; 253 | 254 | Z) 255 | value=25 256 | ;; 257 | 258 | a) 259 | value=26 260 | ;; 261 | 262 | b) 263 | value=27 264 | ;; 265 | 266 | c) 267 | value=28 268 | ;; 269 | 270 | d) 271 | value=29 272 | ;; 273 | 274 | e) 275 | value=30 276 | ;; 277 | 278 | f) 279 | value=31 280 | ;; 281 | 282 | g) 283 | value=32 284 | ;; 285 | 286 | h) 287 | value=33 288 | ;; 289 | 290 | i) 291 | value=34 292 | ;; 293 | 294 | j) 295 | value=35 296 | ;; 297 | 298 | k) 299 | value=36 300 | ;; 301 | 302 | l) 303 | value=37 304 | ;; 305 | 306 | m) 307 | value=38 308 | ;; 309 | 310 | n) 311 | value=39 312 | ;; 313 | 314 | o) 315 | value=40 316 | ;; 317 | 318 | p) 319 | value=41 320 | ;; 321 | 322 | q) 323 | value=42 324 | ;; 325 | 326 | r) 327 | value=43 328 | ;; 329 | 330 | s) 331 | value=44 332 | ;; 333 | 334 | t) 335 | value=45 336 | ;; 337 | 338 | u) 339 | value=46 340 | ;; 341 | 342 | v) 343 | value=47 344 | ;; 345 | 346 | w) 347 | value=48 348 | ;; 349 | 350 | x) 351 | value=49 352 | ;; 353 | 354 | y) 355 | value=50 356 | ;; 357 | 358 | z) 359 | value=51 360 | ;; 361 | 362 | 0) 363 | value=52 364 | ;; 365 | 366 | 1) 367 | value=53 368 | ;; 369 | 370 | 2) 371 | value=54 372 | ;; 373 | 374 | 3) 375 | value=55 376 | ;; 377 | 378 | 4) 379 | value=56 380 | ;; 381 | 382 | 5) 383 | value=57 384 | ;; 385 | 386 | 6) 387 | value=58 388 | ;; 389 | 390 | 7) 391 | value=59 392 | ;; 393 | 394 | 8) 395 | value=60 396 | ;; 397 | 398 | 9) 399 | value=61 400 | ;; 401 | 402 | "$index62Character") 403 | value=62 404 | ;; 405 | 406 | "$index63Character") 407 | value=63 408 | ;; 409 | 410 | '=') 411 | if [ $valueShift -eq 18 ]; then 412 | core_exitError $core_commandLine_exitCode_DATAERR "'=' can start a triple in base64-encoded data" 413 | fi 414 | equalsCount=$((equalsCount+1)) 415 | value=0 416 | ;; 417 | 418 | *) 419 | core_exitError $core_commandLine_exitCode_DATAERR "Unexpected character '$character' in base64-encoded data" 420 | ;; 421 | 422 | esac 423 | 424 | accumulatedValue=$(( (value << valueShift) + accumulatedValue)) 425 | 426 | if [ $valueShift -ne 0 ]; then 427 | valueShift=$((valueShift-6)) 428 | continue 429 | fi 430 | 431 | valueShift=18 432 | 433 | # First byte 434 | printf "\\$(printf '%o' $((accumulatedValue >> 16)))" 435 | 436 | # Second byte 437 | printf "\\$(printf '%o' $(((accumulatedValue >> 8) & 255)))" 438 | 439 | # Third byte 440 | printf "\\$(printf '%o' $((accumulatedValue & 255)))" 441 | 442 | done 443 | 444 | case $valueShift in 445 | 446 | 18) 447 | : 448 | ;; 449 | 450 | 12) 451 | core_exitError $core_commandLine_exitCode_DATAERR "Missing final character in base64-encoded data" 452 | ;; 453 | 454 | 8) 455 | printf "\\$(printf '%o' $((accumulatedValue >> 16)))" 456 | ;; 457 | 458 | 0) 459 | printf "\\$(printf '%o' $((accumulatedValue >> 16)))" 460 | printf "\\$(printf '%o' $(((accumulatedValue >> 8) & 255)))" 461 | ;; 462 | 463 | esac 464 | 465 | } 466 | -------------------------------------------------------------------------------- /children.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core trap 6 | core_usesIn core/variable array 7 | 8 | core_children_initialise() 9 | { 10 | core_trap_addOnCleanUp core_children_killAll 11 | } 12 | core_functions_register _core_functions core_children_initialise 13 | 14 | core_dependency_requires '*' kill 15 | _core_children_killAll_callback() 16 | { 17 | local pid 18 | for pid in "$@" 19 | do 20 | kill -TERM "$pid" 2>/dev/null || true 21 | done 22 | } 23 | 24 | core_children_killAll() 25 | { 26 | if core_variable_array_isSet _core_children_childrenToRemoveOnExit; then 27 | core_variable_array_passToFunctionAsArguments _core_children_childrenToRemoveOnExit _core_children_killAll_callback 28 | fi 29 | } 30 | 31 | core_children_killOnExit() 32 | { 33 | local childPid 34 | for childPid in "$@" 35 | do 36 | core_variable_array_append _core_children_childrenToRemoveOnExit "$childPid" 37 | done 38 | } 39 | -------------------------------------------------------------------------------- /commandLine.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | # Based on sysexits.h (refer to FreeBSD man pages at http://www.gsp.com/cgi-bin/man.cgi?topic=sysexits) 6 | 7 | # successful termination (aka EXIT_SUCCESS in stdlib.h) 8 | core_commandLine_exitCode_OK=0 9 | core_dependency_declares core_commandLine_exitCode_OK 10 | 11 | # Not in sysexit, but so commonly used (aka EXIT_FAILURE in stdlib.h) 12 | core_commandLine_exitCode_FAILURE=1 13 | core_dependency_declares core_commandLine_exitCode_FAILURE 14 | 15 | # Not in sysexit, misuse of builtin 16 | core_commandLine_exitCode_MISUSEBUILTIN=2 17 | core_dependency_declares core_commandLine_exitCode_MISUSEBUILTIN 18 | 19 | # command line usage error 20 | core_commandLine_exitCode_USAGE=64 21 | core_dependency_declares core_commandLine_exitCode_USAGE 22 | 23 | # data format error 24 | core_commandLine_exitCode_DATAERR=65 25 | core_dependency_declares core_commandLine_exitCode_DATAERR 26 | 27 | # cannot open input 28 | core_commandLine_exitCode_NOINPUT=66 29 | core_dependency_declares core_commandLine_exitCode_NOINPUT 30 | 31 | # addressee unknown 32 | core_commandLine_exitCode_NOUSER=67 33 | core_dependency_declares core_commandLine_exitCode_NOUSER 34 | 35 | # host name unknown 36 | core_commandLine_exitCode_NOHOST=68 37 | core_dependency_declares core_commandLine_exitCode_NOHOST 38 | 39 | # service unavailable 40 | core_commandLine_exitCode_UNAVAILABLE=69 41 | core_dependency_declares core_commandLine_exitCode_UNAVAILABLE 42 | 43 | # internal software error 44 | core_commandLine_exitCode_SOFTWARE=70 45 | core_dependency_declares core_commandLine_exitCode_SOFTWARE 46 | 47 | # system error (e.g., can't fork) 48 | core_commandLine_exitCode_OSERR=71 49 | core_dependency_declares core_commandLine_exitCode_OSERR 50 | 51 | # critical OS file missing 52 | core_commandLine_exitCode_OSFILE=72 53 | core_dependency_declares core_commandLine_exitCode_OSFILE 54 | 55 | # can't create (user) output file 56 | core_commandLine_exitCode_CANTCREAT=73 57 | core_dependency_declares core_commandLine_exitCode_CANTCREAT 58 | 59 | # input/output error 60 | core_commandLine_exitCode_IOERR=74 61 | core_dependency_declares core_commandLine_exitCode_IOERR 62 | 63 | # temp failure; user is invited to retry 64 | core_commandLine_exitCode_TEMPFAIL=75 65 | core_dependency_declares core_commandLine_exitCode_TEMPFAIL 66 | 67 | # remote error in protocol 68 | core_commandLine_exitCode_PROTOCOL=76 69 | core_dependency_declares core_commandLine_exitCode_PROTOCOL 70 | 71 | # permission denied 72 | core_commandLine_exitCode_NOPERM=77 73 | core_dependency_declares core_commandLine_exitCode_NOPERM 74 | 75 | # configuration error 76 | core_commandLine_exitCode_CONFIG=78 77 | core_dependency_declares core_commandLine_exitCode_CONFIG 78 | 79 | if ! core_functions_exists _program_commandLine_helpMessage; then 80 | _program_commandLine_helpMessage() 81 | { 82 | : 83 | } 84 | fi 85 | 86 | # Width is 80 cols; standard Parallels VM is 100 cols 87 | core_commandLine_helpMessage() 88 | { 89 | # Defaults 90 | _program_commandLine_helpMessage_usage="[OPTION]..." 91 | _program_commandLine_helpMessage_description="Does nothing." 92 | _program_commandLine_helpMessage_options="" 93 | _program_commandLine_helpMessage_optionsSpacing=' ' 94 | _program_commandLine_helpMessage_configurationKeys="" 95 | _program_commandLine_helpMessage_examples="" 96 | 97 | _program_commandLine_helpMessage 98 | 99 | printf '%s' Usage: "${_program_name} ${_program_commandLine_helpMessage_usage} 100 | ${_program_commandLine_helpMessage_description} 101 | 102 | -h, --help ${_program_commandLine_helpMessage_optionsSpacing}display this help and exit 103 | -v, --verbose [LEVEL] ${_program_commandLine_helpMessage_optionsSpacing}specify more than once to increase verbosity or 104 | ${_program_commandLine_helpMessage_optionsSpacing}optionally set LEVEL to 0 - 2. Defaults to 0. 105 | -q, --quiet ${_program_commandLine_helpMessage_optionsSpacing}specify to reduce verbosity 106 | --version ${_program_commandLine_helpMessage_optionsSpacing}output version information and exit${_program_commandLine_helpMessage_options} 107 | -- ${_program_commandLine_helpMessage_optionsSpacing}end of options 108 | 109 | Notes 110 | Long options with values may also be specified with '=', eg --verbose=2 as well 111 | as --verbose 2. Separate options from operands (non-options) by using '--'. 112 | This prevents interpretation of non-options as options. Concatenating short 113 | options with arguments (eg -v2) is not supported. 114 | 115 | Configuration 116 | This program can be configured by creating files in the form 'key=value' in the 117 | files and folders:- 118 | 119 | ${_program_etcPath}/${_program_name}/rc 120 | ${_program_etcPath}/${_program_name}/rc.d 121 | HOME/.${_program_name}/rc 122 | HOME/.${_program_name}/rc.d 123 | ${_program_namespace}_RC 124 | ${_program_namespace}_RC_D 125 | 126 | Locations ending '.d' are folders which are searched for files. All files in a 127 | folder are used in shell glob-expansion order. HOME, ${_program_namespace}_RC and 128 | ${_program_namespace}_RC_D are environment variables. If the variable 129 | does not exist, or is blacklisted, the location is ignored. 130 | Blacklisting is done by specifying:- 131 | 132 | core_configuration_blacklist VARIABLE_NAME 133 | 134 | in a configuration file. This allows the system administrator to prevent 135 | overridding. 136 | 137 | Files are used in the order above. If a file does not exist, it is ignored. 138 | Those under a 'etc' folder must have the following permissions set:- 139 | 140 | * They are owned by root. 141 | * They are not group writable. 142 | * They are not world writable. 143 | * They do not reside in a group writable directory. 144 | * They do not reside in a world writable directory. 145 | * They are not a symbolic link to a file residing in a group or world 146 | writable directory. 147 | 148 | If the permissions are not set, the file is ignored. 149 | 150 | Configuration Keys 151 | 152 | ${_program_namespace}_verbose $(core_init_verbosity) Controls message logging on stderr 153 | ${_program_namespace}_language $(core_init_language) Controls sort language${_program_commandLine_helpMessage_configurationKeys} 154 | Values should be single or double-quoted if they contain whitespace. 155 | 156 | Examples 157 | ${_program_commandLine_helpMessage_examples} 158 | Path Files 159 | A path file is used to define the location of essential programs used during 160 | initial bootstrapping. It also defines a packageManager to automatically 161 | install any missing dependencies. 162 | " 163 | } 164 | 165 | core_commandLine_defaultLicenseMessage() 166 | { 167 | printf '%s' "LICENSE terms are documented in the COPYRIGHT file at the top-level directory of this distribution." 168 | } 169 | 170 | core_commandLine_versionMessage() 171 | { 172 | if [ -z "$_program_package_or_build" ]; then 173 | local _program_package_or_build_x='' 174 | else 175 | local _program_package_or_build_x="($_program_package_or_build) " 176 | fi 177 | 178 | if core_variable_isSet _program_copyrightAndLicenseStatement; then 179 | local copyrightAndLicenseStatement="$_program_copyrightAndLicenseStatement" 180 | else 181 | local copyrightAndLicenseStatement="$(core_commandLine_defaultLicenseMessage)" 182 | fi 183 | 184 | printf '%s' \ 185 | "$_program_name ${_program_package_or_build_x}$_program_version 186 | Created using shellfire (https://github.com/shellfire-dev/shellfire) 187 | $copyrightAndLicenseStatement" 188 | } 189 | 190 | core_commandLine_exitVersion() 191 | { 192 | core_commandLine_versionMessage 1>&2 193 | exit $core_commandLine_exitCode_OK 194 | } 195 | 196 | core_commandLine_exitHelp() 197 | { 198 | core_commandLine_helpMessage 1>&2 199 | exit $core_commandLine_exitCode_OK 200 | } 201 | 202 | core_commandLine_exitBadCommandLine() 203 | { 204 | core_commandLine_helpMessage 1>&2 205 | core_message FAIL "$1" 206 | exit $core_commandLine_exitCode_USAGE 207 | } 208 | 209 | core_commandLine_setLanguageDefaults() 210 | { 211 | core_variable_unset LANG 212 | core_variable_unset LC_COLLATE 213 | core_variable_unset LC_CTYPE 214 | core_variable_unset LC_MESSAGES 215 | core_variable_unset LC_MONETARY 216 | core_variable_unset LC_NUMERIC 217 | core_variable_unset LC_TIME 218 | core_variable_unset LC_ALL 219 | 220 | local language="$(core_init_language)" 221 | 222 | export LANG="$language" 223 | export LC_COLLATE="$language" 224 | export LC_CTYPE="$language" 225 | export LC_MESSAGES="$language" 226 | export LC_MONETARY="$language" 227 | export LC_NUMERIC="$language" 228 | export LC_TIME="$language" 229 | export LC_ALL="" 230 | 231 | # ? Also LANGUAGE, a GNU gettext extension? 232 | # ignored if locale is set to 'C' 233 | # pt is same as pt_PT for this variable 234 | # export LANGUAGE=sv:de for swedish then german 235 | } 236 | 237 | # yes-argumentless 238 | # yes-argumented 239 | # yes-optionally-argumented 240 | # no 241 | core_commandLine_optionExists() 242 | { 243 | local optionName="$1" 244 | 245 | case "$optionName" in 246 | 247 | h|help) 248 | echo yes-argumentless 249 | ;; 250 | 251 | v|verbose) 252 | echo yes-optionally-argumented 253 | ;; 254 | 255 | q|quiet) 256 | echo yes-argumentless 257 | ;; 258 | 259 | version) 260 | echo yes-argumentless 261 | ;; 262 | 263 | *) 264 | _program_commandLine_optionExists 265 | ;; 266 | 267 | esac 268 | } 269 | 270 | if ! core_functions_exists _program_commandLine_optionExists; then 271 | _program_commandLine_optionExists() 272 | { 273 | echo 'no' 274 | } 275 | fi 276 | 277 | core_commandLine_processOptionWithoutArgument() 278 | { 279 | case "$optionName" in 280 | 281 | h|help) 282 | core_commandLine_exitHelp 283 | ;; 284 | 285 | v|verbose) 286 | local currentVerbosity=$(core_init_verbosity) 287 | core_variable_setVariable ${_program_namespace}_verbose $((currentVerbosity+1)) 288 | ;; 289 | 290 | q|quiet) 291 | local currentVerbosity=$(core_init_verbosity) 292 | if [ $currentVerbosity -gt 0 ]; then 293 | core_variable_setVariable ${_program_namespace}_verbose $((currentVerbosity-1)) 294 | fi 295 | ;; 296 | 297 | version) 298 | core_commandLine_exitVersion 299 | ;; 300 | 301 | *) 302 | _program_commandLine_processOptionWithoutArgument 303 | ;; 304 | 305 | esac 306 | } 307 | 308 | if ! core_functions_exists _program_commandLine_processOptionWithoutArgument; then 309 | _program_commandLine_processOptionWithoutArgument() 310 | { 311 | : 312 | } 313 | fi 314 | 315 | core_commandLine_processOptionWithArgument() 316 | { 317 | case "$optionName" in 318 | 319 | v|verbose) 320 | core_validate_isUnsignedInteger $core_commandLine_exitCode_USAGE 'option' "$optionNameIncludingHyphens" "$optionValue" 321 | 322 | core_variable_setVariable ${_program_namespace}_verbose "$optionValue" 323 | ;; 324 | 325 | *) 326 | _program_commandLine_processOptionWithArgument 327 | ;; 328 | 329 | esac 330 | } 331 | 332 | if ! core_functions_exists _program_commandLine_processOptionWithArgument; then 333 | _program_commandLine_processOptionWithArgument() 334 | { 335 | : 336 | } 337 | fi 338 | 339 | # This can be confused with XF86-style long options (eg -find) 340 | core_commandLine_parseConcatenatedOptionsWithoutEquals() 341 | { 342 | local arguments="-${optionName}" 343 | local optstring=":${optionName}" 344 | local lastOption=${#optionName} 345 | local OPTARG 346 | local OPTERR 347 | local OPTIND=1 348 | 349 | # Is this is a conjoined -o option? [Note we do not support -ab2, where a is optionless but b takes an argument, eg tar -xvfmytar.tar does not pass mytar.tar to the -f option] 350 | local possibleOptionName="$(core_variable_firstCharacter "${optionName}")" 351 | local possibleOptionValue="$(core_variable_allButFirst "${optionName}")" 352 | 353 | case "$(core_commandLine_optionExists "$possibleOptionName")" in 354 | 355 | yes-argumented|yes-optionally-argumented) 356 | optionName="$possibleOptionName" 357 | optionValue="$possibleOptionValue" 358 | core_commandLine_processOptionWithArgument 359 | shouldContinueAfterParsingConcatenatedOptions=1 360 | return 361 | ;; 362 | 363 | esac 364 | 365 | while getopts "$optstring" optionName "$arguments" 366 | do 367 | optionNameIncludingHyphens="-${optionName}" 368 | argument="$optionNameIncludingHyphens" 369 | 370 | if [ $OPTIND -eq $lastOption ]; then 371 | return 0 372 | fi 373 | 374 | case "$(core_commandLine_optionExists "$optionName")" in 375 | 376 | yes-argumentless|yes-optionally-argumented) 377 | core_commandLine_processOptionWithoutArgument 378 | ;; 379 | 380 | yes-argumented) 381 | core_commandLine_exitBadCommandLine "The option '${optionNameIncludingHyphens}' requires an argument which could not be specified" 382 | ;; 383 | 384 | no|'') 385 | core_commandLine_exitBadCommandLine "The short option (concatenated with others) '${optionNameIncludingHyphens}' is not known" 386 | ;; 387 | 388 | *) 389 | core_exitError $core_commandLine_exitCode_SOFTWARE "Please implement yes-argumented, yes-argumentless, yes-optionally-argumented or no for option '$optionName' in _program_commandLine_optionExists()" 390 | ;; 391 | 392 | esac 393 | 394 | done 395 | } 396 | 397 | core_commandLine_parse() 398 | { 399 | if core_functions_exists _program_commandLine_parse; then 400 | _program_commandLine_parse "$@" 401 | else 402 | core_commandLine_parsePosix "$@" 403 | fi 404 | } 405 | 406 | # POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html 407 | # We support combined options, eg -xvf TAR.tar, including those with an argument 408 | # We partly support concatenated arguments (ie instead -o arg, -oarg, but not -xvfTAR.tar for example) 409 | # We do not support XF86-style options such as '-find', although we could (but it seems a little odd) 410 | # An argument of '-' is treated as the first of the non-option arguments, NOT as delimiting the start of the non-options (we use -- for that) 411 | core_commandLine_parsePosix() 412 | { 413 | _program_commandLine_parseInitialise 414 | 415 | local argument 416 | local parsingOptionArguments=0 417 | while [ $# -ne 0 ] 418 | do 419 | local argument="$1" 420 | 421 | if core_variable_startsWith "$argument" '--' ; then 422 | 423 | shift 1 424 | 425 | if [ "$argument" = '--' ]; then 426 | break 427 | fi 428 | 429 | # Parse GNU-style long options 430 | case "$argument" in 431 | 432 | # eg --log-level=debug (handles spaces and multiple = signs correctly) 433 | --*=*) 434 | local optionNameIncludingHyphens="${argument%%=*}" 435 | local optionName="${optionNameIncludingHyphens##--}" 436 | local optionValue="${argument#*=}" 437 | 438 | case "$(core_commandLine_optionExists "$optionName")" in 439 | 440 | yes-argumentless) 441 | core_commandLine_exitBadCommandLine "The option '${optionNameIncludingHyphens}' does not take values (such as '$optionValue')" 442 | ;; 443 | 444 | yes-argumented|yes-optionally-argumented) 445 | core_commandLine_processOptionWithArgument 446 | ;; 447 | 448 | no|'') 449 | core_commandLine_exitBadCommandLine "The long option (with =value) '${optionNameIncludingHyphens}' does not exist" 450 | ;; 451 | 452 | *) 453 | core_exitError $core_commandLine_exitCode_SOFTWARE "Please implement yes-argumented, yes-argumentless, yes-optionally-argumented or no for option '$optionName' in _program_commandLine_optionExists()" 454 | ;; 455 | esac 456 | ;; 457 | 458 | # eg --help and --verbose [level] 459 | --*) 460 | local optionNameIncludingHyphens="$argument" 461 | local optionName="${argument##--}" 462 | 463 | case "$(core_commandLine_optionExists "$optionName")" in 464 | 465 | yes-argumentless) 466 | core_commandLine_processOptionWithoutArgument 467 | ;; 468 | 469 | yes-argumented) 470 | if [ $# -eq 0 ]; then 471 | core_commandLine_exitBadCommandLine "The option '${optionNameIncludingHyphens}' requires an argument which was not specified" 472 | fi 473 | local optionValue="$1" 474 | shift 1 475 | core_commandLine_processOptionWithArgument 476 | ;; 477 | 478 | yes-optionally-argumented) 479 | if [ $# -eq 0 ]; then 480 | core_commandLine_processOptionWithoutArgument 481 | break 482 | fi 483 | local optionValue="$1" 484 | if core_variable_startsWith "$optionValue" '--' ; then 485 | core_commandLine_processOptionWithoutArgument 486 | else 487 | shift 1 488 | core_commandLine_processOptionWithArgument 489 | fi 490 | ;; 491 | 492 | no|'') 493 | core_commandLine_exitBadCommandLine "The long option '${optionNameIncludingHyphens}' is not known" 494 | ;; 495 | 496 | *) 497 | core_exitError $core_commandLine_exitCode_SOFTWARE "Please implement yes-argumented, yes-argumentless, yes-optionally-argumented or no for option '$optionName' in _program_commandLine_optionExists()" 498 | ;; 499 | 500 | esac 501 | ;; 502 | 503 | *) 504 | core_exitError $core_commandLine_exitCode_SOFTWARE "The function core_commandLine_parse failed on argument '$argument', the line was '$@'" 505 | ;; 506 | esac 507 | 508 | elif core_variable_startsWith "$argument" '-' ; then 509 | 510 | # In some legacy programs, this is equivalent to '--'. It can also be a valid non-option argument (eg stdin). We treat it as the latter. 511 | if [ "$argument" = '-' ]; then 512 | break 513 | fi 514 | 515 | shift 1 516 | 517 | # Processing short options (-t, -v, etc) 518 | 519 | case "$argument" in 520 | 521 | # eg -l='debug' 522 | -*=*) 523 | local optionNameIncludingHyphens="${argument%%=*}" 524 | local optionName="${optionNameIncludingHyphens##-}" 525 | local optionValue="${argument#*=}" 526 | if [ ${#optionNameIncludingHyphens} -gt 2 ]; then 527 | # When this returns, all options will have been consumed apart from the last one, and optionName/optionNameIncludingHyphens will be a single option 528 | core_commandLine_parseConcatenatedOptionsWithoutEquals 529 | fi 530 | 531 | case "$(core_commandLine_optionExists "$optionName")" in 532 | 533 | yes-argumentless) 534 | core_commandLine_exitBadCommandLine "The option '$optionNameIncludingHyphens' does not take values (such as '$optionValue')" 535 | ;; 536 | 537 | yes-argumented|yes-optionally-argumented) 538 | core_commandLine_processOptionWithArgument 539 | ;; 540 | 541 | no|'') 542 | core_commandLine_exitBadCommandLine "The short option '$optionNameIncludingHyphens' is not known" 543 | ;; 544 | 545 | *) 546 | core_exitError $core_commandLine_exitCode_SOFTWARE "Please implement yes-argumented, yes-argumentless, yes-optionally-argumented or no for option '$optionName' in _program_commandLine_optionExists()" 547 | ;; 548 | 549 | esac 550 | 551 | ;; 552 | 553 | # eg -h, -hv, -v2 554 | -*) 555 | local optionNameIncludingHyphens="$argument" 556 | local optionName="${argument##-}" 557 | if [ ${#optionNameIncludingHyphens} -gt 2 ]; then 558 | 559 | # Is this is a conjoined -o option? [Note we do not support -ab2, where a is optionless but b takes an argument] 560 | local possibleOptionName="$(core_variable_firstCharacter "${optionName}")" 561 | local possibleOptionValue="$(core_variable_allButFirst "${optionName}")" 562 | 563 | case "$(core_commandLine_optionExists "$possibleOptionName")" in 564 | 565 | yes-argumented|yes-optionally-argumented) 566 | optionName="$possibleOptionName" 567 | optionValue="$possibleOptionValue" 568 | core_commandLine_processOptionWithArgument 569 | continue 570 | ;; 571 | 572 | esac 573 | 574 | # When this returns, all options will have been consumed apart from the last one, and optionName/optionNameIncludingHyphens will be a single option 575 | local shouldContinueAfterParsingConcatenatedOptions=0 576 | core_commandLine_parseConcatenatedOptionsWithoutEquals 577 | if [ $shouldContinueAfterParsingConcatenatedOptions ]; then 578 | continue 579 | fi 580 | fi 581 | 582 | case "$(core_commandLine_optionExists "$optionName")" in 583 | 584 | yes-argumentless) 585 | core_commandLine_processOptionWithoutArgument 586 | ;; 587 | 588 | yes-argumented) 589 | if [ $# -eq 0 ]; then 590 | core_commandLine_exitBadCommandLine "The option '${optionNameIncludingHyphens}' requires an argument which was not specified" 591 | fi 592 | local optionValue="$1" 593 | shift 1 594 | core_commandLine_processOptionWithArgument 595 | ;; 596 | 597 | yes-optionally-argumented) 598 | if [ $# -eq 0 ]; then 599 | core_commandLine_processOptionWithoutArgument 600 | break 601 | fi 602 | local optionValue="$1" 603 | if core_variable_startsWith "$optionValue" '--' ; then 604 | core_commandLine_processOptionWithoutArgument 605 | else 606 | shift 1 607 | core_commandLine_processOptionWithArgument 608 | fi 609 | ;; 610 | 611 | no|'') 612 | core_commandLine_exitBadCommandLine "The short option '${optionNameIncludingHyphens}' is not known" 613 | ;; 614 | 615 | *) 616 | core_exitError $core_commandLine_exitCode_SOFTWARE "Please implement yes-argumented, yes-argumentless, yes-optionally-argumented or no for option '$optionName' in _program_commandLine_optionExists()" 617 | ;; 618 | 619 | esac 620 | ;; 621 | 622 | *) 623 | core_exitError $core_commandLine_exitCode_SOFTWARE "The function core_commandLine_parse failed on argument '$argument', the line was '$@'" 624 | ;; 625 | 626 | esac 627 | else 628 | # start of non-options 629 | break 630 | fi 631 | done 632 | 633 | _program_commandLine_handleNonOptions "$@" 634 | 635 | _program_commandLine_validate 636 | } 637 | 638 | if ! core_functions_exists _program_commandLine_parseInitialise; then 639 | _program_commandLine_parseInitialise() 640 | { 641 | : 642 | } 643 | fi 644 | 645 | if ! core_functions_exists _program_commandLine_handleNonOptions; then 646 | _program_commandLine_handleNonOptions() 647 | { 648 | if [ $# -ne 0 ]; then 649 | core_commandLine_exitBadCommandLine "Non-options are not accepted" 650 | fi 651 | } 652 | fi 653 | 654 | if ! core_functions_exists _program_commandLine_validate; then 655 | _program_commandLine_validate() 656 | { 657 | : 658 | } 659 | fi 660 | -------------------------------------------------------------------------------- /compatibility.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core functions 6 | 7 | core_init_defines core_compatibility_basename 8 | core_init_defines core_compatibility_which 9 | core_init_defines core_compatibility_whichNoOutput 10 | 11 | core_compatibility_dirname() 12 | { 13 | local converted="${1%/*}" 14 | if [ "$converted" = "$1" ]; then 15 | printf '%s' '.' 16 | else 17 | printf '%s' "$converted" 18 | fi 19 | } 20 | 21 | _core_compatibility_builtInDoesNotExist() 22 | { 23 | local builtInName="$1" 24 | local value="$(PATH='' core_compatibility_which "$builtInName")" 25 | if [ "$builtInName" = "$value" ]; then 26 | return 1 27 | fi 28 | return 0 29 | } 30 | 31 | # dash by default escapes backslashes, other echos behave differently. This way is defensive. 32 | core_compatibility_echo() 33 | { 34 | printf '%s\n' "$1" 35 | } 36 | 37 | core_dependency_requires '*' sleep 38 | core_compatibility_sleepSupportsFractionalSeconds() 39 | { 40 | sleep 0.0001 2>/dev/null 41 | } 42 | 43 | core_usesIn core functions 44 | 45 | core_compatibility_execute() 46 | { 47 | core_functions_execute _core_compatibility_functions 48 | } 49 | 50 | core_compatibility_setSaneShellOptions() 51 | { 52 | : 53 | } 54 | core_functions_register _core_compatibility_functions core_compatibility_setSaneShellOptions 55 | 56 | core_compability_installPushdAndPopd() 57 | { 58 | # bash, zsh are known to support this 59 | if _core_compatibility_builtInDoesNotExist pushd; then 60 | 61 | if ! _core_compatibility_builtInDoesNotExist popd; then 62 | core_exitError $core_commandLine_exitCode_SOFTWARE "Weird shell does not have pushd but does have popd (?feature detection bug?)!" 63 | fi 64 | 65 | _core_init_compatibility_pushdCount=0 66 | 67 | pushd() 68 | { 69 | local path="$1" 70 | eval "core_init_pushdStack${_core_init_compatibility_pushdCount}='$(pwd)'" 71 | _core_init_compatibility_pushdCount=$((_core_init_compatibility_pushdCount+1)) 72 | cd "$path" 1>/dev/null 73 | } 74 | 75 | popd() 76 | { 77 | _core_init_compatibility_pushdCount=$((_core_init_compatibility_pushdCount-1)) 78 | eval "local path=\"\$core_init_pushdStack${_core_init_compatibility_pushdCount}\"" 79 | eval "unset core_init_pushdStack${_core_init_compatibility_pushdCount}" 80 | cd "$path" 1>/dev/null 81 | } 82 | 83 | else 84 | 85 | pushd() 86 | { 87 | builtin pushd "$@" 1>/dev/null 88 | } 89 | 90 | popd() 91 | { 92 | builtin popd "$@" 1>/dev/null 93 | } 94 | 95 | fi 96 | } 97 | core_functions_register _core_compatibility_functions core_compability_installPushdAndPopd 98 | 99 | core_compability_installSource() 100 | { 101 | # bash, zsh are known to support this 102 | if _core_compatibility_builtInDoesNotExist source; then 103 | 104 | # Done using as eval to workaround a bug in BusyBox's ash shell when the 'source' directive is compiled in 105 | # BusyBox's ash parser evaluates this code not at 'if-time' but at evaluation of the surrounding code 106 | # Yuck 107 | eval 'source() 108 | { 109 | . "$@" 110 | }' 111 | 112 | fi 113 | } 114 | core_functions_register _core_compatibility_functions core_compability_installSource 115 | -------------------------------------------------------------------------------- /configuration.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | # Consider breaking this out 6 | core_usesIn core path variable 7 | 8 | core_configuration_blacklist() 9 | { 10 | core_variable_array_append _core_configuration_blacklisted "$@" 11 | } 12 | 13 | # Rules taken from GNU rush 14 | core_dependency_requires '*' ls 15 | _core_configuration_validateConfigurationFileIsInsecurelyOwned() 16 | { 17 | # We do not do checks for /usr/local/etc (as this can be user-owned in Homebrew) or /opt/etc 18 | if core_variable_doesNotStartWith "$actualPath" '/etc'; then 19 | return 1 20 | fi 21 | 22 | # We rely on ls as stat varies widely (GNU new vs GNU old vs BSD), and feature checking is painful 23 | # Example on MAC -rw-r--r--@ 1 501 20 171202 11 Sep 08:48 miscellany/logo.key 24 | # Example on LINUX -rw-r--r-- 1 1000 1000 3637 Sep 8 08:37 .bashrc 25 | 26 | local permissions 27 | local links 28 | local uid 29 | local gid 30 | local size 31 | local garbageDateAndName 32 | IFS=' ' read -r permissions links uid gid size garbageDateAndName <<-EOF 33 | $(ls -a -l -L -n "$actualPath") 34 | EOF 35 | 36 | if [ $uid -ne 0 ]; then 37 | core_message WARN "Configuration file '$actualPath' is not owned by root; ignoring" 38 | return 0 39 | fi 40 | if [ $gid -ne 0 ]; then 41 | core_message WARN "Configuration file '$actualPath' is not in root's group; ignoring" 42 | return 0 43 | fi 44 | if core_variable_doesNotStartWith "$permissions" '-rw-r--r--'; then 45 | core_message WARN "Configuration file '$actualPath' has permissions that are not -rw-r--r--; ignoring" 46 | return 0 47 | fi 48 | 49 | local parentPath="$(core_compatibility_basename "$actualPath")" 50 | 51 | ls -a -l -L -n "$actualPath" | while IFS=' ' read -r permissions links uid gid size garbageDateAndName 52 | do 53 | if [ "$permissions" = 'total' ]; then 54 | continue 55 | fi 56 | if [ $uid -ne 0 ]; then 57 | core_message WARN "Configuration file '$actualPath' lives in a folder not owned by root; ignoring" 58 | return 0 59 | fi 60 | if [ $gid -ne 0 ]; then 61 | core_message WARN "Configuration file '$actualPath' lives in a folder not owned by root's group; ignoring" 62 | return 0 63 | fi 64 | if core_variable_doesNotStartWith "$permissions" '-rwxr-xr-x'; then 65 | core_message WARN "Configuration file '$actualPath' lives in a folder with permissions not set to '-rwxr-xr-x'; ignoring" 66 | return 0 67 | fi 68 | break 69 | done 70 | 71 | return 1 72 | } 73 | 74 | _core_configuration_load() 75 | { 76 | local actualPath="$1" 77 | if [ ! -e "$actualPath" ]; then 78 | core_message INFO "Configuration file '$actualPath' does not exist; ignoring" 79 | return 0 80 | elif [ -f "$actualPath" ]; then 81 | if [ ! -r "$actualPath" ]; then 82 | core_message WARN "Configuration file '$actualPath' is not readable; ignoring" 83 | return 0 84 | fi 85 | if [ ! -s "$actualPath" ]; then 86 | core_message WARN "Configuration file '$actualPath' is empty; ignoring" 87 | return 0 88 | fi 89 | if [ -x "$actualPath" ]; then 90 | core_message WARN "Configuration file '$actualPath' is executable and should not be; ignoring" 91 | return 0 92 | fi 93 | 94 | if _core_configuration_validateConfigurationFileIsInsecurelyOwned; then 95 | return 0 96 | fi 97 | 98 | . "$actualPath" || core_exitError $core_commandLine_exitCode_OSFILE "Could not load '$actualPath'" 99 | elif [ -d "$actualPath" ]; then 100 | if [ ! -r "$actualPath" ]; then 101 | core_message WARN "Configuration folder '$actualPath' is not readable; ignoring" 102 | return 0 103 | fi 104 | if [ ! -x "$actualPath" ]; then 105 | core_message WARN "Configuration folder '$actualPath' is not searchable; ignoring" 106 | return 0 107 | fi 108 | 109 | local filePath 110 | pushd "$actualPath" 111 | 112 | set +f 113 | for filePath in * 114 | do 115 | set -f 116 | if [ ! -e "$filePath" ]; then 117 | continue 118 | fi 119 | _core_configuration_load "$filePath" 120 | done 121 | set -f 122 | 123 | popd 124 | else 125 | core_message WARN "Configuration path '$actualPath' resolves to neither a file or folder; ignoring" 126 | return 0 127 | fi 128 | } 129 | 130 | core_configuration_loadPath() 131 | { 132 | local environmentVariable="$1" 133 | local folderOrFilePath="$2" 134 | 135 | if core_variable_isUnset "$environmentVariable"; then 136 | return 0 137 | fi 138 | 139 | if core_variable_array_isSet _core_configuration_blacklisted; then 140 | if core_variable_array_contains _core_configuration_blacklisted "$environmentVariable"; then 141 | core_message WARN "Configuration path '\$$environmentVariable/$folderOrFilePath' is blacklisted" 142 | return 0 143 | fi 144 | fi 145 | 146 | local core_variable_indirectValue_result 147 | core_variable_indirectValue "$environmentVariable" 148 | local parentPath="$core_variable_indirectValue_result" 149 | 150 | if [ -z "$folderOrFilePath" ]; then 151 | local actualPath="$parentPath" 152 | else 153 | local actualPath="$parentPath"/"$folderOrFilePath" 154 | fi 155 | 156 | if core_variable_array_contains _core_configuration_alreadyLoaded "$actualPath"; then 157 | return 0 158 | fi 159 | 160 | core_variable_array_append _core_configuration_alreadyLoaded "$actualPath" 161 | 162 | _core_configuration_load "$actualPath" 163 | } 164 | 165 | core_configuration_defaultsBlacklistedEnvironmentVariables='' 166 | core_configuration_load() 167 | { 168 | core_variable_array_initialise _core_configuration_blacklisted 169 | core_variable_array_initialise _core_configuration_alreadyLoaded 170 | 171 | core_configuration_loadPath _program_etcPath "${core_libraryName}"/rc 172 | core_configuration_loadPath _program_etcPath "${core_libraryName}"/rc.d 173 | 174 | core_configuration_loadPath _program_etcPath "${_program_namespace}"/rc 175 | core_configuration_loadPath _program_etcPath "${_program_namespace}"/rc.d 176 | 177 | core_configuration_loadPath HOME ."${core_libraryName}"/rc 178 | core_configuration_loadPath HOME ."${core_libraryName}"/rc.d 179 | 180 | core_configuration_loadPath ${core_libraryName}_RC '' 181 | core_configuration_loadPath ${core_libraryName}_RC_D '' 182 | 183 | core_configuration_loadPath HOME ."${_program_namespace}"/rc 184 | core_configuration_loadPath HOME ."${_program_namespace}"/rc.d 185 | 186 | core_configuration_loadPath ${_program_namespace}_RC '' 187 | core_configuration_loadPath ${_program_namespace}_RC_D '' 188 | } 189 | 190 | core_usesIn core compatibility 191 | core_configuration_defaults() 192 | { 193 | core_variable_setVariableIfUnset ${_program_namespace}_language $(core_init_language) 194 | core_variable_setVariableIfUnset ${_program_namespace}_verbose $(core_init_verbosity) 195 | } 196 | -------------------------------------------------------------------------------- /core.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_init_defines core_message 6 | core_init_defines core_exitError 7 | core_init_defines core_TODO 8 | core_init_defines core_uses 9 | core_init_defines core_usesIn 10 | 11 | core_usesIn core configuration snippet commandLine compatibility dependency functions file path trap umask validate variable 12 | core_usesIn core children temporaryFiles 13 | 14 | core_functions_register _core_functions \ 15 | core_compatibility_execute \ 16 | core_configuration_load \ 17 | core_configuration_defaults \ 18 | core_umask_setDefault \ 19 | core_commandLine_setLanguageDefaults \ 20 | core_commandLine_parse \ 21 | core_dependency_installDependencies 22 | -------------------------------------------------------------------------------- /dependency/check.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_releaseFile() 6 | { 7 | local releaseFileName="$1" 8 | local packageManager="$2" 9 | 10 | if [ -f /etc/"$releaseFileName" ]; then 11 | core_dependency_packageManager="$packageManager" 12 | return 0 13 | fi 14 | return 1 15 | } 16 | 17 | core_dependency_check_packageManagersWithPaths='Alpine CentOS Cygwin Debian Fedora FreeBSD MacOsXPkgsrc Mageia NetBSD OpenBSD RedHat SuSE Homebrew' 18 | core_dependency_declares core_dependency_check_packageManagersWithPaths 19 | core_usesIn core/dependency/check Alpine CentOS Cygwin Debian Fedora FreeBSD Homebrew MacOsXPkgsrc Mageia NetBSD OpenBSD RedHat SuSE 20 | -------------------------------------------------------------------------------- /dependency/check/Alpine.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_Alpine_checkFunction() 6 | { 7 | core_dependency_check_releaseFile alpine-release Alpine 8 | } 9 | core_functions_register _core_dependency_check_functions core_dependency_check_Alpine_checkFunction 10 | 11 | core_dependency_check_Alpine_extractUnqualifiedPackageName() 12 | { 13 | local fullyQualifiedPackageName="$1" 14 | 15 | local repositoryName 16 | local packageName 17 | _core_dependency_check_Alpine_parsePackageName 18 | 19 | printf '%s' "$packageName" 20 | } 21 | 22 | _core_dependency_check_Alpine_parsePackageName() 23 | { 24 | repositoryName='' 25 | packageName='' 26 | IFS='/' read -r repositoryName packageName <<-EOF 27 | ${fullyQualifiedPackageName} 28 | EOF 29 | 30 | if [ -z "$packageName" ]; then 31 | repositoryName='' 32 | packageName="$repositoryName" 33 | fi 34 | } 35 | 36 | core_dependency_requires Alpine apk id cat 37 | core_dependency_check_Alpine_packageManager() 38 | { 39 | local apkVerbosity="--no-progress" 40 | 41 | case $(core_init_verbosity) in 42 | 43 | 0) 44 | apkVerbosity="$apkVerbosity --quiet" 45 | ;; 46 | 47 | 1) 48 | : 49 | ;; 50 | 51 | *) 52 | apkVerbosity="$apkVerbosity --verbose" 53 | ;; 54 | 55 | esac 56 | 57 | local ourCurrentId="$(id -u)" 58 | if [ "$ourCurrentId" = 0 ]; then 59 | core_message NOTICE "Updating apk package manager (may take some time)" 60 | apk ${apkVerbosity} update 61 | elif core_compatibility_whichNoOutput sudo; then 62 | core_message NOTICE "Updating apk package manager (may take some time)" 63 | sudo -p "Please enter the password for %p for sudo to apk update: " apk ${apkVerbosity} update 64 | else 65 | core_message INFO "Not running as root and sudo not found, so not installing packages '$@'" 66 | return 0 67 | fi 68 | 69 | if core_variable_isSet core_dependency_check_forcePackageManagerUpgradeDuringInstall; then 70 | if [ $core_dependency_check_forcePackageManagerUpgradeDuringInstall -eq 1 ]; then 71 | core_message INFO "Upgrading apk package manager (may take some time)" 72 | if [ "$ourCurrentId" = 0 ]; then 73 | apk ${apkVerbosity} upgrade 74 | else 75 | sudo -p "Please enter the password for %p for sudo to run apk upgrade: " apk ${apkVerbosity} upgrade 76 | fi 77 | fi 78 | fi 79 | 80 | local fullyQualifiedPackageName 81 | local repositoryName 82 | local packageName 83 | for fullyQualifiedPackageName in "$@" 84 | do 85 | local apkOptions="$apkVerbosity" 86 | _core_dependency_check_Alpine_parsePackageName 87 | if [ -n "$repositoryName" ]; then 88 | apkOptions="$apkOptions --repository '$repositoryName'" 89 | fi 90 | 91 | if [ "$ourCurrentId" = 0 ]; then 92 | apk $apkOptions add "$@" 93 | else 94 | sudo -p "Please enter the password for %p for sudo to install packages using apk: " apk $apkOptions add "$@" 95 | fi 96 | done 97 | } 98 | -------------------------------------------------------------------------------- /dependency/check/CentOS.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_CentOS_checkFunction() 6 | { 7 | core_dependency_check_releaseFile centos-release CentOS 8 | } 9 | core_functions_register _core_dependency_check_functions core_dependency_check_CentOS_checkFunction 10 | 11 | _core_dependency_check_CentOS_parsePackageName() 12 | { 13 | repositoryName='' 14 | packageName='' 15 | IFS='/' read -r repositoryName packageName <<-EOF 16 | ${fullyQualifiedPackageName} 17 | EOF 18 | 19 | if [ -z "$packageName" ]; then 20 | repositoryName='' 21 | packageName="$repositoryName" 22 | fi 23 | } 24 | 25 | core_dependency_check_CentOS_extractUnqualifiedPackageName() 26 | { 27 | local fullyQualifiedPackageName="$1" 28 | 29 | local repositoryName 30 | local packageName 31 | _core_dependency_check_CentOS_parsePackageName 32 | 33 | printf '%s' "$packageName" 34 | } 35 | 36 | core_dependency_requires CentOS sudo yum 37 | core_dependency_requires Fedora sudo yum 38 | core_dependency_requires RedHat sudo yum 39 | core_dependency_check_CentOS_packageManager() 40 | { 41 | if [ $(core_init_verbosity) -gt 0 ]; then 42 | local yumVerbosity="" 43 | else 44 | local yumVerbosity="--quiet" 45 | fi 46 | 47 | local ourCurrentId="$(id -u)" 48 | if [ "$ourCurrentId" = 0 ]; then 49 | yum ${yumVerbosity} makecache 50 | elif core_compatibility_whichNoOutput sudo; then 51 | sudo -p "Please enter the password for %p for sudo to update yum: " yum ${yumVerbosity} makecache 52 | else 53 | core_message INFO "Not running as root and sudo not found, so not installing packages '$@'" 54 | return 0 55 | fi 56 | 57 | local repositoryName 58 | local packageName 59 | local fullyQualifiedPackageName 60 | local functionName 61 | for fullyQualifiedPackageName in "$@" 62 | do 63 | _core_dependency_check_CentOS_parsePackageName 64 | if [ -z "$repositoryName" ]; then 65 | 66 | if [ "$ourCurrentId" = 0 ]; then 67 | yum ${yumVerbosity} -y install "$packageName" 68 | else 69 | sudo -p "Please enter the password for %p for sudo to run yum install $packageName: " yum ${yumVerbosity} -y install "$packageName" 70 | fi 71 | else 72 | functionName=_core_dependency_check_CentOS_installRepository_${repositoryName} 73 | if ! core_functions_exists "$functionName"; then 74 | core_exitError "Package '$packageName' is in an unsupported repository '$repositoryName'" 75 | else 76 | ${functionName} 77 | fi 78 | if [ "$repositoryName" = 'repoforge' ]; then 79 | repositoryName=rpmforge 80 | fi 81 | 82 | if [ "$ourCurrentId" = 0 ]; then 83 | yum ${yumVerbosity} -y --disablerepo="*" --enablerepo="$repositoryName" install "$packageName" 84 | else 85 | sudo -p "Please enter the password for %p for sudo to run yum install $packageName: " yum ${yumVerbosity} -y --disablerepo="*" --enablerepo="$repositoryName" install "$packageName" 86 | fi 87 | fi 88 | 89 | done 90 | } 91 | 92 | core_dependency_requires CentOS yum head 93 | core_dependency_requires Fedora yum head 94 | core_dependency_requires RedHat yum head 95 | _core_dependency_check_CentOS_detectIfYumSupportsAssumeYes() 96 | { 97 | yum --version | head -n 1 98 | } 99 | 100 | core_dependency_requires CentOS rpm grep 101 | core_dependency_requires Fedora rpm grep 102 | core_dependency_requires RedHat rpm grep 103 | _core_dependency_check_CentOS_checkPackageInstalled() 104 | { 105 | # doesn't work for packages installed by rpm (eg rpmforge) 106 | # yum --quiet list installed "$1" 1>/dev/null 2>/dev/null; then 107 | # might work 108 | # yum list | grep "$1" 109 | 110 | local packageName="$1" 111 | rpm -qa | grep -q "^${packageName}-" 112 | } 113 | 114 | core_dependency_requires CentOS sudo yum 115 | core_dependency_requires Fedora sudo yum 116 | core_dependency_requires RedHat sudo yum 117 | _core_dependency_check_CentOS_installRepository_epel() 118 | { 119 | if _core_dependency_check_CentOS_checkPackageInstalled 'epel-release'; then 120 | return 0 121 | fi 122 | 123 | sudo -p "Please enter the password for %p for sudo to run yum install epel-release: " yum ${yumVerbosity} -y install epel-release 124 | } 125 | 126 | core_dependency_requires CentOS sed uname sudo rpm curl yum 127 | core_dependency_requires Fedora sed uname sudo rpm curl yum 128 | core_dependency_requires RedHat sed uname sudo rpm curl yum 129 | _core_dependency_check_CentOS_installRepository_repoforge() 130 | { 131 | if _core_dependency_check_CentOS_checkPackageInstalled 'rpmforge-release'; then 132 | return 0 133 | fi 134 | local TMP_FILE 135 | core_temporaryFiles_newFileToRemoveOnExit 136 | local temporaryFile="$TMP_FILE" 137 | 138 | # We're supposed to use lsb_release -r, but it isn't installed by default on CentOS 6 or 7 (and the install pulls in 156 packages for the redhat-lsb package it's in) 139 | sed -e 's/release /release./g' -e 's/.* release\.//g' -e 's/ .*$//g' /etc/redhat-release >"$temporaryFile" 140 | local release 141 | local garbage 142 | IFS='.' read -r release garbage <"$temporaryFile" 143 | 144 | local downloadUrl="http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el${release}.rf.$(uname -m).rpm" 145 | 146 | local repoForgeReleaseRpmFilePath="$temporaryFile" 147 | 148 | sudo -p "Please enter the password for %p for sudo to import repoforge repository's key (please note this is only available over _HTTP_): " rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt 2>/dev/null || true 149 | 150 | curl --silent --location --url "$downloadUrl" >"$repoForgeReleaseRpmFilePath" 151 | 152 | rpm -K "$repoForgeReleaseRpmFilePath" 1>/dev/null 2>/dev/null || core_exitError $core_commandLine_exitCode_IOERR "Downloaded repoforge package corrupt or tampered with" 153 | 154 | sudo -p "Please enter the password for %p for sudo to add the repoforge repository" rpm --quiet -ivh "$repoForgeReleaseRpmFilePath" 155 | 156 | sudo -p "Please enter the password for %p for sudo to update yum: " yum --quiet makecache 157 | } 158 | -------------------------------------------------------------------------------- /dependency/check/Cygwin.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_Cygwin_checkFunction() 6 | { 7 | if [ -x /bin/cygcheck.exe ]; then 8 | core_dependency_packageManager="Cygwin" 9 | return 0 10 | fi 11 | return 1 12 | } 13 | core_functions_register _core_dependency_check_functions core_dependency_check_Cygwin_checkFunction 14 | 15 | core_dependency_check_Cygwin_extractUnqualifiedPackageName() 16 | { 17 | local fullyQualifiedPackageName="$1" 18 | printf '%s' "$fullyQualifiedPackageName" 19 | } 20 | 21 | #core_dependency_requires Cygwin setup-x86 22 | core_dependency_check_Cygwin_packageManager() 23 | { 24 | core_message INFO "Please run the Cygwin setup-x86.exe to install the packages '$@'" 25 | } 26 | -------------------------------------------------------------------------------- /dependency/check/Debian.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_Debian_checkFunction() 6 | { 7 | core_dependency_check_releaseFile debian_version Debian 8 | } 9 | core_functions_register _core_dependency_check_functions core_dependency_check_Debian_checkFunction 10 | 11 | core_dependency_check_Debian_extractUnqualifiedPackageName() 12 | { 13 | local fullyQualifiedPackageName="$1" 14 | printf '%s' "$fullyQualifiedPackageName" 15 | } 16 | 17 | core_dependency_requires Debian sudo apt-get id 18 | core_dependency_check_Debian_packageManager() 19 | { 20 | if [ $(core_init_verbosity) -gt 0 ]; then 21 | local aptVerbosity="" 22 | else 23 | local aptVerbosity=" --quiet" 24 | fi 25 | 26 | local ourCurrentId="$(id -u)" 27 | if [ "$ourCurrentId" = 0 ]; then 28 | core_message NOTICE "Updating apt-get package manager (may take some time)" 29 | apt-get${aptVerbosity} update 30 | elif core_compatibility_whichNoOutput sudo; then 31 | core_message NOTICE "Updating apt-get package manager (may take some time)" 32 | sudo -p "Please enter the password for %p for sudo to apt-get update: " apt-get${aptVerbosity} update 33 | else 34 | core_message INFO "Not running as root and sudo not found, so not installing packages '$@'" 35 | return 0 36 | fi 37 | 38 | if core_variable_isSet core_dependency_check_forcePackageManagerUpgradeDuringInstall; then 39 | if [ $core_dependency_check_forcePackageManagerUpgradeDuringInstall -eq 1 ]; then 40 | core_message INFO "Upgrading apt-get package manager (may take some time)" 41 | if [ "$ourCurrentId" = 0 ]; then 42 | apt-get${aptVerbosity} dist-upgrade 43 | else 44 | sudo -p "Please enter the password for %p for sudo to run apt-get dist-upgrade: " apt-get${aptVerbosity} dist-upgrade 45 | fi 46 | fi 47 | fi 48 | 49 | if [ "$ourCurrentId" = 0 ]; then 50 | apt-get${aptVerbosity} --no-install-recommends --yes --no-upgrade install "$@" 51 | else 52 | sudo -p "Please enter the password for %p for sudo to install packages using apt-get: " apt-get${aptVerbosity} --no-install-recommends --yes --no-upgrade install "$@" 53 | fi 54 | } 55 | -------------------------------------------------------------------------------- /dependency/check/Fedora.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_Fedora_checkFunction() 6 | { 7 | core_dependency_check_releaseFile fedora-release Fedora 8 | } 9 | core_functions_register _core_dependency_check_functions core_dependency_check_Fedora_checkFunction 10 | 11 | core_dependency_check_Fedora_extractUnqualifiedPackageName() 12 | { 13 | core_dependency_check_CentOS_extractUnqualifiedPackageName "$@" 14 | } 15 | 16 | core_dependency_check_Fedora_packageManager() 17 | { 18 | core_dependency_check_CentOS_packageManager "$@" 19 | } 20 | -------------------------------------------------------------------------------- /dependency/check/FreeBSD.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_FreeBSD_checkFunction() 6 | { 7 | if [ -x /bin/freebsd-version ]; then 8 | return 0 9 | fi 10 | return 1 11 | } 12 | core_functions_register _core_dependency_check_functions core_dependency_check_FreeBSD_checkFunction 13 | 14 | core_dependency_check_FreeBSD_extractUnqualifiedPackageName() 15 | { 16 | printf '%s' "$1" 17 | } 18 | 19 | core_dependency_requires FreeBSD id pkg 20 | core_dependency_check_FreeBSD_packageManager() 21 | { 22 | local ourCurrentId="$(id -u)" 23 | 24 | local pkgPath 25 | if core_compatibility_whichNoOutput pkg; then 26 | pkgPath='pkg' 27 | elif [ ! -x /usr/sbin/pkg ]; then 28 | pkgPath=/usr/sbin/pkg 29 | else 30 | core_message INFO "Please bootstrap FreeBSD's pkg manager by running /usr/sbin/pkg" 31 | return 0 32 | fi 33 | 34 | if [ "$ourCurrentId" = 0 ]; then 35 | "$pkgPath" install -q -y "$@" 36 | else 37 | local sudoCommandPath 38 | if core_compatibility_whichNoOutput sudo; then 39 | sudoCommandPath=sudo 40 | elif [ -x /usr/local/bin/sudo ]; then 41 | sudoCommandPath=/usr/local/bin/sudo 42 | else 43 | core_message INFO "Not running as root and sudo not found, so not installing packages using '$pkgPath'" 44 | return 0 45 | fi 46 | 47 | "$sudoCommandPath" "$pkgPath" install -q -y "$@" 48 | fi 49 | } 50 | -------------------------------------------------------------------------------- /dependency/check/Homebrew.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_Homebrew_checkFunction() 6 | { 7 | if core_compatibility_whichNoOutput brew; then 8 | core_dependency_packageManager="Homebrew" 9 | return 0 10 | fi 11 | return 1 12 | } 13 | core_functions_register _core_dependency_check_functions core_dependency_check_Homebrew_checkFunction 14 | 15 | core_dependency_check_Homebrew_extractUnqualifiedPackageName() 16 | { 17 | local fullyQualifiedPackageName="$1" 18 | core_compatibility_basename "$fullyQualifiedPackageName" 19 | } 20 | 21 | core_dependency_requires Homebrew brew 22 | core_dependency_check_Homebrew_packageManager() 23 | { 24 | # We can't cache this in an array as it changes on every loop 25 | _core_dependency_check_Homebrew_packageManager_tapExists() 26 | { 27 | local existingTap 28 | brew tap | while IFS='' read -r existingTap 29 | do 30 | if [ "$existingTap" = "$tap" ]; then 31 | return 0 32 | fi 33 | done 34 | return 1 35 | } 36 | 37 | local packageToInstall 38 | local package 39 | _core_dependency_check_Homebrew_packageManager_installTaps() 40 | { 41 | local tap 42 | for packageToInstall in "$@" 43 | do 44 | tap="$(core_compatibility_dirname "$packageToInstall")" 45 | if [ "$tap" = '.' ]; then 46 | continue 47 | fi 48 | if _core_dependency_check_Homebrew_packageManager_tapExists; then 49 | continue 50 | fi 51 | brew tap "$tap" 1>/dev/null 2>/dev/null 52 | done 53 | } 54 | _core_dependency_check_Homebrew_packageManager_installTaps "$@" 55 | 56 | core_message NOTICE "Updating Homebrew package manager (may take some time)" 57 | brew update 58 | 59 | if core_variable_isSet core_dependency_check_forcePackageManagerUpgradeDuringInstall; then 60 | if [ $core_dependency_check_forcePackageManagerUpgradeDuringInstall -eq 1 ]; then 61 | core_message INFO "Upgrading Homebrew package manager (may take some time)" 62 | brew upgrade 63 | fi 64 | fi 65 | 66 | for packageToInstall in "$@" 67 | do 68 | package="$(core_compatibility_basename "$packageToInstall")" 69 | if brew --prefix "$package" 1>/dev/null 2>/dev/null; then 70 | local checkFolderPath="$(brew --prefix "$package")" 71 | if [ -d "$checkFolderPath" ]; then 72 | continue 73 | fi 74 | fi 75 | 76 | brew install "$packageToInstall" 77 | done 78 | 79 | # fakeroot required a brew link 80 | } 81 | 82 | core_dependency_check_Homebrew_installPackageManagerIfRequired() 83 | { 84 | if core_compatibility_whichNoOutput brew; then 85 | return 0 86 | fi 87 | 88 | core_message NOTICE "Installing Homebrew package manager" 89 | ruby -e "$(curl -fsSL 'https://raw.githubusercontent.com/Homebrew/install/master/install')" 90 | 91 | core_message INFO "Doctoring (sic) Homebrew package manager" 92 | brew doctor 93 | 94 | # check is /usr/local/{s}bin is on the path 95 | } 96 | -------------------------------------------------------------------------------- /dependency/check/MacOsXPkgsrc.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_MacOsXPkgsrc_checkFunction() 6 | { 7 | if ! core_compatibility_whichNoOutput uname; then 8 | return 0 9 | fi 10 | 11 | if [ "$(uname -s)" = 'Darwin' ]; then 12 | 13 | core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevision='2015Q3' 14 | core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevisionSha1='c150c0db1daddb4ec49592a7563c2838760bfb8b' 15 | core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevisionGpgKey='0xDE817B8E' 16 | core_dependency_check_MacOsXPkgsrc_DefaultPathPkgin=/opt/pkg/bin/pkgin 17 | core_dependency_check_MacOsXPkgsrc_DefaultPathPkg_add=/opt/pkg/bin/pkg_src 18 | core_dependency_check_MacOsXPkgsrc_DefaultPathSudo=/usr/bin/sudo 19 | 20 | core_dependency_packageManager='MacOsXPkgsrc' 21 | if [ -d /opt/pkg ]; then 22 | # To work correctly, PATH=/opt/pkg/sbin:/opt/pkg/bin:"$PATH" 23 | return 0 24 | else 25 | core_dependency_check_MacOsXPkgsrc_installPackageManagerIfRequired 26 | fi 27 | fi 28 | return 1 29 | } 30 | core_functions_register _core_dependency_check_functions core_dependency_check_MacOsXPkgsrc_checkFunction 31 | 32 | core_dependency_check_MacOsXPkgsrc_extractUnqualifiedPackageName() 33 | { 34 | printf '%s' "$1" 35 | } 36 | 37 | # https://pkgsrc.joyent.com/install-on-osx/ 38 | # https://www.netbsd.org/docs/pkgsrc/ 39 | core_dependency_requires MacOsXPkgsrc uname curl shasum gpg sudo tar rm 40 | core_dependency_check_MacOsXPkgsrc_installPackageManagerIfRequired() 41 | { 42 | if core_compatibility_whichNoOutput pkgin; then 43 | return 0 44 | fi 45 | 46 | local os="$(uname -s)" 47 | local architecture="$(uname -m)" 48 | 49 | local TMP_FILE 50 | 51 | core_temporaryFiles_newFolderToRemoveOnExit 52 | local downloadedFilePath="$TMP_FILE" 53 | 54 | core_temporaryFiles_newFolderToRemoveOnExit 55 | local downloadedSignatureFilePath="$TMP_FILE" 56 | 57 | core_message NOTICE "Downloading pkgsrc package manager" 58 | curl --location --silent "https://pkgsrc.joyent.com/packages/${os}/bootstrap/bootstrap-${core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevision}-${architecture}.tar.gz" >"$downloadedFilePath" 59 | 60 | core_message NOTICE "Verifying SHA-1 hash for pkgsrc" 61 | local sha="$(shasum "$downloadedFilePath")" 62 | if [ "${sha%% *}" != "$core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevisionSha1" ]; then 63 | core_exitError $core_commandLine_exitCode_DATAERR "Downloaded pkgsrc bootstrap has incorrect SHA-1 hash" 64 | fi 65 | 66 | core_message NOTICE "Downloading pkgsrc package manager signature" 67 | curl --location --silent "https://pkgsrc.joyent.com/packages/${os}/bootstrap/bootstrap-${core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevision}-${architecture}.tar.gz.asc" >"$downloadedSignatureFilePath" 68 | 69 | core_message NOTICE "Downloading GPG key $core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevisionGpgKey" 70 | gpg --quiet --recv-keys "$core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevisionGpgKey" 2>/dev/null 71 | 72 | core_message NOTICE "Verifying GPG signature for pkgsrc" 73 | if ! gpg --verify "$downloadedSignatureFilePath" "$downloadedFilePath"; then 74 | core_exitError $core_commandLine_exitCode_DATAERR "Downloaded pkgsrc bootstrap has invalid signature!" 75 | fi 76 | 77 | # Do not wait until exit, as these are big files in the temp file system 78 | rm -f "$downloadedSignatureFilePath" "$downloadedFilePath" 79 | 80 | core_message NOTICE "Installing pkgsrc package manager" 81 | core_dependency_checkMacOsxPkgsrc_packageManager_sudo tar -zxpf "$downloadedFilePath" -C / 82 | core_dependency_checkMacOsxPkgsrc_packageManager_sudo rm -rf /var/db/pkgin 83 | core_dependency_checkMacOsxPkgsrc_packageManager_sudo "$core_dependency_check_MacOsXPkgsrc_DefaultPathPkgin" -y update 84 | } 85 | 86 | core_dependency_requires MacOsXPkgsrc id 87 | core_dependency_check_MacOsXPkgsrc_packageManager() 88 | { 89 | local ourCurrentId="$(id -u)" 90 | local pkginDefaultPath= 91 | local pkg_addDefaultPath=/opt/pkg/sbin/pkg_add 92 | 93 | if core_compatibility_whichNoOutput pkgin; then 94 | core_dependency_check_MacOsXPkgsrc_packageManager_pkgin pkgin "$@" 95 | elif [ -x "$core_dependency_check_MacOsXPkgsrc_DefaultPathPkgin" ]; then 96 | core_dependency_check_MacOsXPkgsrc_packageManager_pkgin "$core_dependency_check_MacOsXPkgsrc_DefaultPathPkgin" "$@" 97 | elif core_compatibility_whichNoOutput pkg_add; then 98 | core_dependency_check_MacOsXPkgsrc_packageManager_pkg_add pkg_add "$@" 99 | elif [ -x "$core_dependency_check_MacOsXPkgsrc_DefaultPathPkg_add" ]; then 100 | core_dependency_check_MacOsXPkgsrc_packageManager_pkg_add "$core_dependency_check_MacOsXPkgsrc_DefaultPathPkg_add" "$@" 101 | else 102 | core_message INFO "No package manager (pkgin or pkg_add) found, so not installing packages" 103 | fi 104 | } 105 | 106 | core_dependency_checkMacOsxPkgsrc_packageManager_sudo() 107 | { 108 | local sudoCommandPath 109 | if core_compatibility_whichNoOutput sudo; then 110 | sudoCommandPath=sudo 111 | elif [ -x "$core_dependency_check_MacOsXPkgsrc_DefaultPathSudo" ]; then 112 | sudoCommandPath="$core_dependency_check_MacOsXPkgsrc_DefaultPathSudo" 113 | else 114 | core_message INFO "Not running as root and sudo not found, so not installing packages using pkgin" 115 | return 0 116 | fi 117 | 118 | "$sudoCommandPath" "$@" 119 | } 120 | 121 | 122 | core_dependency_requires MacOsXPkgsrc uname sudo pkgin 123 | core_dependency_check_MacOsXPkgsrc_packageManager_pkgin() 124 | { 125 | local pathToPkgin="$1" 126 | shift 1 127 | 128 | { 129 | if [ ! -s /opt/pkg/etc/pkgin/repositories.conf ]; then 130 | if core_variable_isUnset PKG_REPOS; then 131 | local os="$(uname -s)" 132 | local architecture="$(uname -m)" 133 | export PKG_REPOS="http://pkgsrc.joyent.com/packages/${os}/${core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevision}/${architecture}/All" 134 | fi 135 | fi 136 | 137 | if [ "$ourCurrentId" = 0 ]; then 138 | "$pathToPkgin" -y update 139 | "$pathToPkgin" -y install "$@" 140 | else 141 | core_dependency_checkMacOsxPkgsrc_packageManager_sudo -p "Please enter the password for %p for sudo to update the package list using pkgin: " "$pathToPkgin" -y update 142 | core_dependency_checkMacOsxPkgsrc_packageManager_sudo -p "Please enter the password for %p for sudo to install packages using pkgin: " "$pathToPkgin" -y install "$@" 143 | fi 144 | } 145 | } 146 | 147 | core_dependency_requires MacOsXPkgsrc uname cut sudo pkg_add env 148 | core_dependency_check_MacOsXPkgsrc_packageManager_pkg_add() 149 | { 150 | local pathToPkgAdd="$1" 151 | shift 1 152 | 153 | { 154 | if core_variable_isUnset PKG_PATH; then 155 | 156 | local os="$(uname -s)" 157 | local architecture="$(uname -m)" 158 | 159 | export PKG_PATH="https://pub.allbsd.org/pub/pkgsrc/packages/${os}/${core_dependency_check_MacOsXPkgsrc_JoyentMacOsXRevision}/${architecture}/All" 160 | fi 161 | 162 | if [ "$ourCurrentId" = 0 ]; then 163 | "$pathToPkgAdd" "$@" 164 | else 165 | core_dependency_checkMacOsxPkgsrc_packageManager_sudo -p "Please enter the password for %p for sudo to install packages using pkg_add: " "$pathToPkgAdd" "$@" 166 | fi 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /dependency/check/Mageia.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_Mageia_checkFunction() 6 | { 7 | core_dependency_check_releaseFile mageia-release Mageia 8 | } 9 | core_functions_register _core_dependency_check_functions core_dependency_check_Mageia_checkFunction 10 | 11 | core_dependency_check_Mageia_extractUnqualifiedPackageName() 12 | { 13 | printf '%s' "$1" 14 | } 15 | 16 | core_dependency_requires Mageia sudo urpmi 17 | core_dependency_check_Mageia_packageManager() 18 | { 19 | local ourCurrentId="$(id -u)" 20 | if [ "$ourCurrentId" = 0 ]; then 21 | urpmi --auto --quiet "$@" 22 | elif core_compatibility_whichNoOutput sudo; then 23 | sudo -p "Please enter the password for %p for sudo to run urpmi: " urpmi --auto --quiet "$@" 24 | else 25 | core_message INFO "Not running as root and sudo not found, so not installing packages '$@'" 26 | fi 27 | } 28 | -------------------------------------------------------------------------------- /dependency/check/NetBSD.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_dependency_check_NetBSD_checkFunction() 6 | { 7 | if [ ! -f /etc/release ]; then 8 | return 1 9 | fi 10 | 11 | local operatingSystem 12 | local versionSlashArchitecture 13 | IFS=' ' read -r operatingSystem versionSlashArchitecture /dev/null; then 20 | gem install "$gem" 21 | fi 22 | done 23 | } 24 | -------------------------------------------------------------------------------- /file.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core temporaryFiles 6 | core_dependency_requires '*' awk 7 | core_file_characterByCharacter() 8 | { 9 | local filePath="$1" 10 | shift 1 11 | 12 | local TMP_FILE 13 | core_temporaryFiles_newFileToRemoveOnExit 14 | local singleCharactersFile="$TMP_FILE" 15 | 16 | core_file_characterByCharacterCreate "$filePath" "$singleCharactersFile" 17 | 18 | local callback 19 | local character 20 | { 21 | while IFS='' read -r character 22 | do 23 | for callback in "$@" 24 | do 25 | $callback 26 | done 27 | done 28 | } <"$singleCharactersFile" 29 | 30 | rm -f "$singleCharactersFile" 31 | } 32 | 33 | core_file_characterByCharacterCreate() 34 | { 35 | local inputFile="$1" 36 | local outputFile="$2" 37 | 38 | awk ' 39 | BEGIN { 40 | srand() 41 | FS="" 42 | RS="n/o/m/a/t/c/h" rand() 43 | } 44 | 45 | { 46 | for (i = 1; i <= NF; i++) 47 | { 48 | if ($i ~ /\n/) 49 | { 50 | printf "\n" 51 | } 52 | else 53 | { 54 | print $i 55 | } 56 | } 57 | }' <"$inputFile" >"$outputFile" 58 | } 59 | -------------------------------------------------------------------------------- /functions.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core compatibility 6 | core_usesIn core/variable array 7 | 8 | core_functions_register() 9 | { 10 | local functionsVariableName="$1" 11 | shift 1 12 | 13 | core_variable_array_append "$functionsVariableName" "$@" 14 | core_dependency_declaresAsArray "$functionsVariableName" 15 | } 16 | 17 | core_functions_execute() 18 | { 19 | local functionsVariableName="$1" 20 | shift 1 21 | 22 | if core_variable_isSet "$functionsVariableName"; then 23 | core_variable_array_iterateAsCallbacks "$functionsVariableName" "$@" 24 | fi 25 | } 26 | 27 | # Not perfect by any means; an expanded environment variable with content of 'a shell function', say, could fail this test 28 | core_functions_exists() 29 | { 30 | local functionName="$1" 31 | if ! type "$functionName" 1>/dev/null 2>/dev/null; then 32 | return 1 33 | fi 34 | 35 | local arg0 36 | local arg1 37 | local arg2 38 | local arg3 39 | local arg4 40 | IFS=' ' read -r arg0 arg1 arg2 arg3 arg4 <<-EOF 41 | $(type "$functionName") 42 | EOF 43 | 44 | case "$arg3" in 45 | 46 | # dash 47 | shell) 48 | if [ "$arg4" = 'function' ]; then 49 | return 0 50 | fi 51 | ;; 52 | 53 | # bash 54 | function) 55 | return 0 56 | ;; 57 | 58 | # AIX shell 59 | 'function.') 60 | return 0 61 | ;; 62 | 63 | esac 64 | 65 | return 1 66 | } 67 | -------------------------------------------------------------------------------- /init.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_init_isFattening() 6 | { 7 | core_variable_isSet _program_fattening 8 | } 9 | 10 | core_compatibility_basename() 11 | { 12 | printf '%s' "${1##*/}" 13 | } 14 | 15 | core_compatibility_which() 16 | { 17 | command -v "$1" 18 | } 19 | 20 | core_compatibility_whichNoOutput() 21 | { 22 | core_compatibility_which "$1" 1>/dev/null 2>/dev/null 23 | } 24 | 25 | core_variable_isSet() 26 | { 27 | # These expressions work in all shells bar pdksh 5.2.14, which treats expanded emptiness as unset... 28 | # Other techniques here: http://mywiki.wooledge.org/BashFAQ/083 29 | # eval "[ \"\${$1+set}\" = 'set' ]" 30 | # eval "$(printf '[ "${%s+set}" = '%s' ]' "$1" "set")" 31 | 32 | local x 33 | eval x="\"\${$1+set}\"" 34 | [ "$x" = 'set' ] 35 | } 36 | 37 | core_variable_isUnset() 38 | { 39 | # eval "[ \"\${$1+unset}\" != 'unset' ]" 40 | ! core_variable_isSet "$1" 41 | } 42 | 43 | core_variable_indirectValue() 44 | { 45 | eval "core_variable_indirectValue_result=\"\$${1}\"" 46 | } 47 | 48 | core_init_verbosity() 49 | { 50 | if core_variable_isSet ${_program_namespace}_verbose; then 51 | local core_variable_indirectValue_result 52 | core_variable_indirectValue ${_program_namespace}_verbose 53 | printf '%s' $core_variable_indirectValue_result 54 | else 55 | printf '%s' 0 56 | fi 57 | } 58 | 59 | core_init_language() 60 | { 61 | if core_variable_isSet ${_program_namespace}_language; then 62 | local core_variable_indirectValue_result 63 | core_variable_indirectValue ${_program_namespace}_language 64 | printf '%s' $core_variable_indirectValue_result 65 | else 66 | printf '%s' 'C.UTF-8' 67 | fi 68 | } 69 | 70 | # We're supposed to use tput, but:- 71 | # - It isn't present in BusyBox and Toybox (and other minimal systems without ncurses) 72 | # - It doesn't work on a FreeBSD 10 default install (terminfo db probably missing) 73 | # - terminfo databases are notorious for being broken and incomplete 74 | # So we use ANSI sequences if we recognise the 'TERM' variable 75 | # That stick to a small VT102 / ECMA-48 subset 76 | # And fallback to tput if available 77 | # http://wiki.bash-hackers.org/scripting/terminalcodes 78 | # http://invisible-island.net/xterm/ctlseqs/ctlseqs.html 79 | # http://www.termsys.demon.co.uk/vtansi.htm 80 | # https://www.gnu.org/software/termutils/manual/termutils-2.0/html_chapter/tput_1.html 81 | # https://en.wikipedia.org/wiki/ANSI_escape_code 82 | # http://mywiki.wooledge.org/BashFAQ/037?highlight=%28ps1%29 83 | # “\e[x,y,zm” with x=brightness, y=foreground, z=background. For example: 84 | # “\e[0;33;40m” shows dark (=0) yellow (=33) characters on black (=40) background 85 | core_terminal_ansiSupported() 86 | { 87 | if core_variable_isUnset TERM; then 88 | return 1 89 | fi 90 | 91 | case "$TERM" in 92 | 93 | # xterm-color, xterm-256color, linux-16color, etc 94 | # dtterm on AIX? kterm? others? 95 | xterm*|rxvt*|urxvt*|linux*|vt*) 96 | return 0 97 | ;; 98 | 99 | esac 100 | 101 | return 1 102 | } 103 | 104 | core_terminal_ansiSequence() 105 | { 106 | IFS='' printf "\033[${1}m" 107 | } 108 | 109 | core_terminal_tput() 110 | { 111 | # Defensive syntax (|| true) for systems such as FreeBSD 10 where tput doesn't seem to support 'setaf' et al 112 | # Defensive setting of terminal so unset or empty TERM uses 'dumb', which disables option generation 113 | tput -T"${TERM:-dumb}" "$@" 2>/dev/null || true 114 | } 115 | 116 | core_terminal_colour() 117 | { 118 | if [ ! -t $1 ]; then 119 | return 0 120 | fi 121 | 122 | local terminfoCommand 123 | local ansiGroundCodeBit 124 | case "$2" in 125 | 126 | foreground) 127 | terminfoCommand=setaf 128 | ansiGroundCodeBit=3 129 | ;; 130 | 131 | background) 132 | terminfoCommand=setbf 133 | ansiGroundCodeBit=4 134 | ;; 135 | 136 | esac 137 | 138 | local ansiColorCodeBit 139 | case "$3" in 140 | black) 141 | ansiColorCodeBit=0 142 | ;; 143 | 144 | red) 145 | ansiColorCodeBit=1 146 | ;; 147 | 148 | green) 149 | ansiColorCodeBit=2 150 | ;; 151 | 152 | yellow) 153 | ansiColorCodeBit=3 154 | ;; 155 | 156 | blue) 157 | ansiColorCodeBit=4 158 | ;; 159 | 160 | magenta) 161 | ansiColorCodeBit=5 162 | ;; 163 | 164 | cyan) 165 | ansiColorCodeBit=6 166 | ;; 167 | 168 | white) 169 | ansiColorCodeBit=7 170 | ;; 171 | 172 | default) 173 | ansiColorCodeBit=9 174 | ;; 175 | esac 176 | 177 | if core_terminal_ansiSupported; then 178 | core_terminal_ansiSequence ${ansiGroundCodeBit}${ansiColorCodeBit} 179 | elif core_compatibility_whichNoOutput tput; then 180 | core_terminal_tput $terminfoCommand $ansiColorCodeBit 181 | fi 182 | } 183 | 184 | core_terminal_effect() 185 | { 186 | if [ ! -t $1 ]; then 187 | return 0 188 | fi 189 | shift 1 190 | 191 | local effect 192 | local terminfoCommand 193 | local ansiCode 194 | for effect in "$@" 195 | do 196 | case "$effect" in 197 | 198 | bold) 199 | terminfoCommand=bold 200 | ansiCode=1 201 | ;; 202 | 203 | dim) 204 | terminfoCommand=dim 205 | ansiCode=2 206 | ;; 207 | 208 | # underscore not supported 209 | # $(tput smul)test$(tput rmul) 210 | # vs 211 | # ansiCode=4 212 | 213 | # standout mode (often bold or reversed) 214 | # smso / rmso 215 | 216 | blink) 217 | terminfoCommand=blink 218 | ansiCode=5 219 | ;; 220 | 221 | reversed) 222 | terminfoCommand=rev 223 | ansiCode=7 224 | ;; 225 | 226 | invisible) 227 | terminfoCommand=invis 228 | ansiCode=8 229 | ;; 230 | 231 | esac 232 | 233 | if core_terminal_ansiSupported; then 234 | core_terminal_ansiSequence $ansiCode 235 | elif core_compatibility_whichNoOutput tput; then 236 | core_terminal_tput $terminfoCommand 237 | fi 238 | done 239 | } 240 | 241 | core_terminal_reset() 242 | { 243 | if [ -t $1 ]; then 244 | if core_terminal_ansiSupported; then 245 | core_terminal_ansiSequence 0 246 | elif core_compatibility_whichNoOutput tput; then 247 | core_terminal_tput sgr0 248 | fi 249 | fi 250 | } 251 | 252 | core_message() 253 | { 254 | local messageKind="$1" 255 | local message="$2" 256 | 257 | local shouldEcho=0 258 | local prefix='' 259 | case "$messageKind" in 260 | 261 | FAIL) 262 | prefix="$(core_terminal_effect 2 bold)$(core_terminal_colour 2 foreground red)" 263 | shouldEcho=1 264 | ;; 265 | 266 | WARN) 267 | prefix="$(core_terminal_effect 2 bold)$(core_terminal_colour 2 foreground yellow)" 268 | shouldEcho=1 269 | ;; 270 | 271 | NOTICE) 272 | if [ $(core_init_verbosity) -gt 0 ]; then 273 | prefix="$(core_terminal_colour 2 foreground cyan)" 274 | shouldEcho=1 275 | fi 276 | ;; 277 | 278 | INFO) 279 | if [ $(core_init_verbosity) -gt 1 ]; then 280 | prefix="$(core_terminal_colour 2 foreground white)" 281 | shouldEcho=1 282 | fi 283 | ;; 284 | 285 | TODO) 286 | if [ $(core_init_verbosity) -gt 1 ]; then 287 | prefix="$(core_terminal_effect 2 dim)" 288 | shouldEcho=1 289 | fi 290 | ;; 291 | 292 | DEBUG) 293 | if [ $(core_init_verbosity) -gt 2 ]; then 294 | prefix="$(core_terminal_effect 2 dim)$(core_terminal_colour 2 foreground magenta)" 295 | shouldEcho=1 296 | fi 297 | ;; 298 | 299 | *) 300 | shouldEcho=1 301 | ;; 302 | 303 | esac 304 | 305 | if [ $shouldEcho -eq 1 ]; then 306 | printf '%s%s%s\n' "$prefix" "$_program_name: $messageKind: $message" "$(core_terminal_reset 2)" 1>&2 307 | fi 308 | } 309 | 310 | core_exitError() 311 | { 312 | core_message FAIL "$2" 313 | exit $1 314 | } 315 | 316 | core_TODO() 317 | { 318 | core_message TODO "$*" 319 | } 320 | 321 | if core_init_isFattening; then 322 | core_dependency_declares() 323 | { 324 | _program_fattening_declares "$@" 325 | } 326 | core_dependency_declaresAsArray() 327 | { 328 | local variableName 329 | for variableName in "$@" 330 | do 331 | _program_fattening_declares "$variableName" 332 | _program_fattening_declares "${variableName}_initialised" 333 | done 334 | } 335 | else 336 | core_dependency_declares() 337 | { 338 | : 339 | } 340 | core_dependency_declaresAsArray() 341 | { 342 | : 343 | } 344 | fi 345 | 346 | core_libraryName=shellfire 347 | core_dependency_declares core_libraryName 348 | 349 | _core_dependency_requires='' 350 | core_dependency_declares _core_dependency_requires 351 | core_dependency_requires() 352 | { 353 | # Or '*' for all 354 | _local_packageManager="$1" 355 | if [ -z "$_local_packageManager" ]; then 356 | # core_commandLine_exitCode_SOFTWARE 357 | core_exitError 70 "packageManager can not be empty" 358 | fi 359 | shift 1 360 | 361 | for _local_programName in "$@" 362 | do 363 | if [ -z "$_local_programName" ]; then 364 | # core_commandLine_exitCode_SOFTWARE 365 | core_exitError 70 "programName can not be empty" 366 | fi 367 | _core_dependency_requires="${_core_dependency_requires}${_local_packageManager} ${_local_programName} 368 | " 369 | core_message DEBUG "Requires in packageManager '$_local_packageManager' program '$_local_programName'" 370 | done 371 | 372 | unset _local_packageManager 373 | unset _local_programName 374 | } 375 | 376 | # More for documentation than anything else for now 377 | core_dependency_oneOf() 378 | { 379 | # Or '*' for all 380 | _local_packageManager="$1" 381 | if [ -z "$_local_packageManager" ]; then 382 | # core_commandLine_exitCode_SOFTWARE 383 | core_exitError 70 "packageManager can not be empty" 384 | fi 385 | shift 1 386 | 387 | for _local_programName in "$@" 388 | do 389 | : 390 | done 391 | 392 | unset _local_packageManager 393 | unset _local_programName 394 | } 395 | 396 | # More for documentation than anything else for now 397 | core_dependency_fallback() 398 | { 399 | # eg !bash 400 | _local_condition="$1" 401 | 402 | for _local_programNameOnPath in "$@" 403 | do 404 | : 405 | done 406 | 407 | unset _local_condition 408 | unset _local_programNameOnPath 409 | } 410 | 411 | core_dependency_declares _core_uses_alreadySourced 412 | # Duplicates logic in core/variable/array, but that is a hefty piece to pull in and breaks code (as the bash overrides handle arrays differently) 413 | # Has a defect such that function paths containing $delimiter can be loaded more than once [highly unlikely except as a potential security defect] 414 | # By specifying $1 as not, say, /usr/lib, and $2 as something other than core_libraryName, this code can be used for plugins 415 | core_uses() 416 | { 417 | local libPath="$1" 418 | local libraryName="$2" 419 | shift 2 420 | 421 | local namespacedModule 422 | local moduleName 423 | local sourced 424 | local relativeFunctionsFilePath 425 | local functionsFilePath 426 | 427 | # TODO: Does NOT WORK when using /bin/sh on Mac - implying older bash run as sh is broken 428 | local delimiter="$core_variable_array_delimiter" 429 | 430 | local module 431 | for module in "$@" 432 | do 433 | namespacedModule="$libraryName"/"$module" 434 | 435 | # Skip if already sourced 436 | local originalIFS="$IFS" 437 | local IFS="$delimiter" 438 | if core_variable_isUnset _core_uses_alreadySourced; then 439 | _core_uses_alreadySourced="${namespacedModule}" 440 | else 441 | for alreadySourcedNamespacedFunction in $_core_uses_alreadySourced 442 | do 443 | if [ "$namespacedModule" = "$alreadySourcedNamespacedFunction" ]; then 444 | continue 2 445 | fi 446 | done 447 | _core_uses_alreadySourced="${_core_uses_alreadySourced}${delimiter}${namespacedModule}" 448 | fi 449 | local IFS="$originalIFS" 450 | 451 | # Source 452 | moduleName="$(core_compatibility_basename "$namespacedModule")" 453 | sourced=0 454 | for relativeFunctionsFilePath in "$namespacedModule" "$namespacedModule"/"$moduleName" 455 | do 456 | functionsFilePath="$libPath"/"$relativeFunctionsFilePath".functions 457 | if [ -f "$functionsFilePath" ]; then 458 | # core_commandLine_exitCode_OSFILE 459 | . "$functionsFilePath" || core_exitError 72 "Can not load functions '$functionsFilePath'" 460 | sourced=1 461 | fi 462 | done 463 | if [ $sourced -eq 0 ]; then 464 | # core_commandLine_exitCode_OSFILE 465 | core_exitError 72 "Can not load functions for module '$namespacedModule'" 466 | fi 467 | done 468 | } 469 | 470 | core_usesIn() 471 | { 472 | if [ $# -eq 1 ]; then 473 | local parentNamespace='' 474 | else 475 | local parentNamespace="${1}/" 476 | shift 1 477 | fi 478 | 479 | local module 480 | for module in "$@" 481 | do 482 | core_uses "$_program_libPath" "$core_libraryName" "${parentNamespace}${module}" 483 | done 484 | } 485 | 486 | core_init_defines() 487 | { 488 | : 489 | } 490 | 491 | core_init_init() 492 | { 493 | set -e 494 | set -u 495 | 496 | if [ "${_program_namespace+set}" != 'set' ]; then 497 | _program_namespace="${_program_name}" 498 | fi 499 | } 500 | 501 | core_init_shellDetection() 502 | { 503 | if [ "${KSH_VERSION+set}" = 'set' ]; then 504 | _local_core_init_shellDetection_kshVersion="$KSH_VERSION" 505 | elif [ "${SH_VERSION+set}" = 'set' ]; then 506 | # seems to be set for pdksh when run as sh on OpenBSD (OpenBSD pdksh is modified) 507 | _local_core_init_shellDetection_kshVersion="$SH_VERSION" 508 | else 509 | _local_core_init_shellDetection_kshVersion='' 510 | fi 511 | 512 | if [ -n "$_local_core_init_shellDetection_kshVersion" ]; then 513 | # ksh93: Version JM 93u 2011-02-08 514 | # ksh93: Version AJM 93u+ 2012-08-01 515 | # pdksh: @(#)PD KSH v5.2.14 99/07/13.2 516 | IFS=' ' read -r _local_core_init_shellDetection_version _local_core_init_shellDetection_garbage <<-EOF 517 | ${_local_core_init_shellDetection_kshVersion} 518 | EOF 519 | 520 | case "$_local_core_init_shellDetection_version" in 521 | 522 | # ksh93 523 | 'Version'|'.sh.version') 524 | core_init_shellDetected=ksh93 525 | ;; 526 | 527 | '@(#)PD') 528 | core_init_shellDetected=pdksh 529 | ;; 530 | 531 | '@(#)MIRBSD') 532 | core_init_shellDetected=mksh 533 | ;; 534 | 535 | *) 536 | core_init_shellDetected=unknown-ksh 537 | ;; 538 | 539 | esac 540 | 541 | unset _local_core_init_shellDetection_version 542 | unset _local_core_init_shellDetection_garbage 543 | elif [ "${BASH_VERSION+set}" = 'set' ]; then 544 | core_init_shellDetected=bash 545 | elif [ "${ZSH_VERSION+set}" = 'set' ]; then 546 | core_init_shellDetected=zsh 547 | elif [ "${YASH_VERSION+set}" = 'set' ]; then 548 | core_init_shellDetected=yash 549 | else 550 | core_init_shellDetected=sh 551 | fi 552 | 553 | unset _local_core_init_shellDetection_kshVersion 554 | } 555 | 556 | core_init_enableShellTweaks() 557 | { 558 | # pdksh 5.2.14 barfs if the variable to unset is not set, even if set +u! 559 | # Worse, it refuses to let us override unset with a function. Hence this workaround everyone else has to use 560 | core_variable_unset() 561 | { 562 | unset "$@" 563 | } 564 | 565 | case "$core_init_shellDetected" in 566 | 567 | ksh93) 568 | # Set aliases for ksh93 569 | # https://stackoverflow.com/questions/12000949/scope-of-variables-in-ksh 570 | alias local='typeset' 571 | ;; 572 | 573 | pdksh) 574 | # pdksh 5.2.14 barfs if the variable to unset is not set, even if set +u! 575 | core_variable_unset() 576 | { 577 | set +e 578 | unset "$1" 579 | set -e 580 | } 581 | 582 | # pdksh does not understand that in POSIX '$@' can be unset or empty but is still valid to reference 583 | # As a workaround, we disable unbound checks 584 | set +u 585 | 586 | # AIX pdksh also doesn't understand var=value exec command syntax... (it doesn't export var)! 587 | ;; 588 | 589 | mksh) 590 | # See pdksh entry 591 | set +u 592 | ;; 593 | 594 | yash) 595 | alias local='typeset' 596 | ;; 597 | 598 | esac 599 | } 600 | 601 | core_init_setSaneEnvironmentDefaults() 602 | { 603 | set +o allexport 604 | set -o errexit 605 | set +o ignoreeof 606 | set +o monitor 607 | set +o noclobber 608 | set +o noexec 609 | # aka set -f; disable globbing by default. Note that this is the opposite of usual behaviour 610 | set -o noglob 611 | # Does not work on FreeBSD sh; fine on dash, bash, etc 612 | # set +o nolog 613 | set +o notify 614 | set +o verbose 615 | set +o vi 616 | 617 | # unset will fail if, and only if, we've been source'd and they have been made readonly. Unlikely. 618 | 619 | # MUST be unset before making use of cd 620 | core_variable_unset CDPATH 621 | core_variable_unset HISTSIZE 622 | core_variable_unset MAILCHECK 623 | core_variable_unset MAILPATH 624 | core_variable_unset ENV 625 | core_variable_unset POSIXLY_CORRECT # affects bash, file, GNU grep, etc 626 | 627 | # bash specific 628 | core_variable_unset BASH_ENV 629 | core_variable_unset BASH_XTRACEFD 630 | core_variable_unset FCEDIT 631 | core_variable_unset FIGNORE 632 | core_variable_unset FUNCNEST 633 | core_variable_unset GLOBIGNORE 634 | core_variable_unset HISTCONTROL 635 | core_variable_unset HISTFILE 636 | core_variable_unset HISTFILESIZE 637 | core_variable_unset HISTIGNORE 638 | core_variable_unset HISTTIMEFORMAT 639 | core_variable_unset HOSTFILE 640 | core_variable_unset IGNOREEOF 641 | core_variable_unset INPUTRC 642 | core_variable_unset MAIL 643 | core_variable_unset TMOUT 644 | } 645 | 646 | # http://mywiki.wooledge.org/BashFAQ/028 on $0 647 | # http://mywiki.wooledge.org/Bashism?action=show&redirect=bashism 648 | core_init_findOurNameAndPath() 649 | { 650 | core_init_ourSymlinkName="$(core_compatibility_basename "$0")" 651 | 652 | # can be empty if 'bash file' used or 'bash /dev/null 666 | core_init_ourSymlinkPath="$(pwd)" 667 | core_init_ourPath="$(pwd -P)" 668 | cd - 1>/dev/null 669 | 670 | core_init_ourSymlinkExecutablePath="$core_init_ourSymlinkPath"/"$core_init_ourSymlinkName" 671 | 672 | unset _local_ourSymlinkPathRaw 673 | } 674 | 675 | core_init_doNotRunAsSetUidOrSetGid() 676 | { 677 | # Not a great defence; real purpose is to defeat a sysadmin making this script setuid/setgid:- 678 | # * Happens too late, really - the shell interpreter is running 679 | # * bash allows functions to be exported that can replace builtins (even the builtin builtin) 680 | 681 | if [ -u "$core_init_ourSymlinkExecutablePath" ]; then 682 | # core_commandLine_exitCode_NOPERM 683 | core_exitError 77 "We can not be run with the setuid bit set" 684 | fi 685 | 686 | if [ -g "$core_init_ourSymlinkExecutablePath" ]; then 687 | # core_commandLine_exitCode_NOPERM 688 | core_exitError 77 "We can not be run with setgid bit set" 689 | fi 690 | } 691 | 692 | core_init_shellPreferred='sh' 693 | core_init_determinePreferredShell() 694 | { 695 | IFS=' ' read -r _local_commented_shebang_path _local_shebang_shell _local_remainder <"$core_init_ourSymlinkExecutablePath" 696 | if [ -n "$_local_remainder" ]; then 697 | # core_commandLine_exitCode_SOFTWARE 698 | core_exitError 70 "Passing options to a shell ('#!$_local_shebang_path $_local_shebang_shell $_local_remainder') is not supported" 699 | fi 700 | IFS='!' read -r _local_comment _local_shebang_path <<-EOF 701 | $_local_commented_shebang_path 702 | EOF 703 | 704 | if [ -z "$_local_shebang_shell" ]; then 705 | core_init_shellPreferred="$(core_compatibility_basename "$_local_shebang_path")" 706 | else 707 | if [ "$_local_shebang_path" != '/usr/bin/env' ]; then 708 | # core_commandLine_exitCode_SOFTWARE 709 | core_exitError 70 "All shell scripts should use '/usr/bin/env' with a shell, not #!$_local_shebang_path $shebang_shell" 710 | fi 711 | core_init_shellPreferred="$_local_shebang_shell" 712 | fi 713 | 714 | unset _local_commented_shebang_path 715 | unset _local_shebang_shell 716 | unset _local_remainder 717 | unset _local_comment 718 | unset _local_shebang_path 719 | } 720 | 721 | # Ensures we run under a shell interpreter that we were designed for - no matter what is specified in the shebang 722 | # This works around packaging tools that want '#!/bin/bash', but point to an old version. Needs to be coupled into loading new shell versions. 723 | core_init_rexecUnderCorrectShell() 724 | { 725 | if core_variable_isSet core_init_shell_rexecing; then 726 | if [ "$core_init_shell_rexecing" = "$$" ]; then 727 | # we've been successfully re-exec'd 728 | unset core_init_shell_rexecing 729 | return 0 730 | fi 731 | fi 732 | 733 | # Doesn't defend against bash as sh bugs 734 | if [ "$core_init_shellDetected" = "$core_init_shellPreferred" ]; then 735 | return 0 736 | fi 737 | 738 | if ! core_compatibility_whichNoOutput "$core_init_shellPreferred"; then 739 | #core_commandLine_exitCode_OSFILE 740 | core_exitError 72 "Preferred shell '$core_init_shellPreferred' does not exist on the PATH" 741 | fi 742 | _local_shellPath="$(core_compatibility_which "$core_init_shellPreferred")" 743 | 744 | # exec -a doesn't work in dash 745 | if [ "$core_init_shellDetected" = 'bash' ]; then 746 | # ksh on AIX does not export core_init_shell_rexecing when run as core_init_shell_rexecing=$$ exec $program ... 747 | 748 | # Forces a privileged shell. Not a great defence to Shellshock, but has some value. 749 | # Also possible for ksh and pdksh (?mksh) but ksh doesn't export functions 750 | export core_init_shell_rexecing=$$ 751 | exec "$_local_shellPath" -p "$core_init_ourSymlinkExecutablePath" "$@" 752 | else 753 | export core_init_shell_rexecing=$$ 754 | core_init_shell_rexecing=$$ exec "$_local_shellPath" "$core_init_ourSymlinkExecutablePath" "$@" 755 | fi 756 | 757 | unset _local_shellPath 758 | } 759 | 760 | core_init_initialiseArrayDelimiter() 761 | { 762 | # Choosing a delimiter is unreasonably hard. 763 | # - It needs to work when set in IFS. 764 | # - It has a lifetime longer than the instance run if used for fattening. 765 | # - Various common bash versions have different IFS handling bugs. 766 | # Ideally, we want to use '\000', as it never occurs in file names. However, this is only allowed by zsh 767 | # Near Ideally, '\001' is so rare in file names as to be a good choice. 768 | # - However, bash 3.2 when invoked as sh on Mac OS X or AIX 6 & 7 can't use this. 769 | # - bash 4.1 on CentOS 6.11 seems to have similar issues. 770 | # Fairly rare is `\r' 771 | # - However bash 3.1.X in MinGW MSYS, Gow, etc (various bash-on-windows flavours) can't support this. 772 | # ',' works but is fairly common 773 | 774 | 775 | # We want to use '\001' in IFS as it's rare enough to delimit array elements safely. 776 | # However, some 'popular' versions of bash have IFS bugs which often manifest when bash is run as 'sh' 777 | if core_variable_isSet core_variable_array_delimiter; then 778 | return 0 779 | fi 780 | 781 | if core_variable_isSet _program_arrayDelimiter; then 782 | core_variable_array_delimiter="$_program_arrayDelimiter" 783 | else 784 | core_variable_array_delimiter="$(printf '\r')" 785 | fi 786 | core_dependency_declares core_variable_array_delimiter 787 | } 788 | 789 | _core_init_makePathAbsolute() 790 | { 791 | local variableName="$1" 792 | 793 | if core_variable_isUnset "$variableName"; then 794 | return 0 795 | fi 796 | 797 | local core_variable_indirectValue_result 798 | core_variable_indirectValue "$variableName" 799 | 800 | set +e 801 | 802 | cd "$core_variable_indirectValue_result" 1>/dev/null 2>/dev/null 803 | if [ $? -ne 0 ]; then 804 | set -e 805 | return 0 806 | fi 807 | 808 | local absolutePath="$(pwd -P)" 809 | eval "$variableName"'=$absolutePath' 810 | 811 | cd - 1>/dev/null 812 | 813 | set -e 814 | } 815 | 816 | core_init_makePathsAbsolute() 817 | { 818 | _core_init_makePathAbsolute _program_libPath 819 | _core_init_makePathAbsolute _program_etcPath 820 | _core_init_makePathAbsolute _program_varPath 821 | } 822 | 823 | core_init_workAroundBugInHomeFolderTildeHandlingAndEnsureHOMEIsAlwaysSet() 824 | { 825 | # Weirdly, it seems ~ expansion doesn't work in some contexts in some shells 826 | set +f 827 | cd ~ 1>/dev/null 828 | export HOME="$(pwd -P)" 829 | cd - 1>/dev/null 830 | set -f 831 | } 832 | 833 | core_init_main() 834 | { 835 | core_init_init 836 | core_init_shellDetection 837 | core_init_enableShellTweaks 838 | core_init_setSaneEnvironmentDefaults 839 | core_init_findOurNameAndPath 840 | core_init_determinePreferredShell 841 | core_init_rexecUnderCorrectShell "$@" 842 | core_init_initialiseArrayDelimiter 843 | core_init_makePathsAbsolute 844 | core_init_workAroundBugInHomeFolderTildeHandlingAndEnsureHOMEIsAlwaysSet 845 | 846 | core_usesIn core 847 | if core_functions_exists _program; then 848 | _program 849 | else 850 | : 851 | fi 852 | 853 | if core_init_isFattening; then 854 | return 0 855 | fi 856 | core_functions_execute _core_functions "$@" 857 | ${_program_entrypoint} 858 | } 859 | 860 | core_init_main "$@" 861 | -------------------------------------------------------------------------------- /licences.snippet: -------------------------------------------------------------------------------- 1 | SPDX Identifier SPDX Name Fedora Identifier (Match License Name) 2 | Glide 3dfx Glide License Glide 3 | Abstyles Abstyles License Abstyles 4 | AFL-1.1 Academic Free License v1.1 AFL 5 | AFL-1.2 Academic Free License v1.2 AFL 6 | AFL-2.0 Academic Free License v2.0 AFL 7 | AFL-2.1 Academic Free License v2.1 AFL 8 | AFL-3.0 Academic Free License v3.0 AFL 9 | AMPAS Academy of Motion Picture Arts and Sciences BSD AMPAS BSD 10 | APL-1.0 Adaptive Public License 1.0 11 | Adobe-Glyph Adobe Glyph List License MIT 12 | APAFML Adobe Postscript AFM License APAFML 13 | Adobe-2006 Adobe Systems Incorporated Source Code License Agreement Adobe 14 | AGPL-1.0 Affero General Public License v1.0 AGPLv1 15 | Afmparse Afmparse License Afmparse 16 | Aladdin Aladdin Free Public License 17 | ADSL Amazon Digital Services License ADSL 18 | AMDPLPA AMD's plpa_map.c License AMDPLPA 19 | ANTLR-PD ANTLR Software Rights Notice Public Domain 20 | Apache-1.0 Apache License 1.0 ASL 1.0 21 | Apache-1.1 Apache License 1.1 ASL 1.1 22 | Apache-2.0 Apache License 2.0 ASL 2.0 23 | AML Apple MIT License AML 24 | APSL-1.0 Apple Public Source License 1.0 25 | APSL-1.1 Apple Public Source License 1.1 26 | APSL-1.2 Apple Public Source License 1.2 27 | APSL-2.0 Apple Public Source License 2.0 APSL 2.0 28 | Artistic-1.0 Artistic License 1.0 29 | Artistic-1.0-Perl Artistic License 1.0 (Perl) 30 | Artistic-1.0-cl8 Artistic License 1.0 w/clause 8 31 | Artistic-2.0 Artistic License 2.0 Artistic 2.0 32 | AAL Attribution Assurance License AAL 33 | Bahyph Bahyph License Bahyph 34 | Barr Barr License Barr 35 | Beerware Beerware License Beerware 36 | BitTorrent-1.0 BitTorrent Open Source License v1.0 BitTorrent 37 | BitTorrent-1.1 BitTorrent Open Source License v1.1 BitTorrent 38 | BSL-1.0 Boost Software License 1.0 Boost 39 | Borceux Borceux license Borceux 40 | BSD-2-Clause BSD 2-clause "Simplified" License BSD 41 | BSD-2-Clause-FreeBSD BSD 2-clause FreeBSD License BSD 42 | BSD-2-Clause-NetBSD BSD 2-clause NetBSD License BSD 43 | BSD-3-Clause BSD 3-clause "New" or "Revised" License BSD 44 | BSD-3-Clause-Clear BSD 3-clause Clear License BSD 45 | BSD-4-Clause BSD 4-clause "Original" or "Old" License BSD with advertising 46 | BSD-Protection BSD Protection License BSD Protection 47 | BSD-3-Clause-Attribution BSD with attribution BSD with attribution 48 | BSD-4-Clause-UC BSD-4-Clause (University of California-Specific) BSD 49 | bzip2-1.0.5 bzip2 and libbzip2 License v1.0.5 50 | bzip2-1.0.6 bzip2 and libbzip2 License v1.0.6 51 | Caldera Caldera License 52 | CECILL-1.0 CeCILL Free Software License Agreement v1.0 CeCILL 53 | CECILL-1.1 CeCILL Free Software License Agreement v1.1 CeCILL 54 | CECILL-2.0 CeCILL Free Software License Agreement v2.0 CeCILL 55 | CECILL-B CeCILL-B Free Software License Agreement CeCILL-B 56 | CECILL-C CeCILL-C Free Software License Agreement CeCILL-C 57 | ClArtistic Clarified Artistic License Artistic clarified 58 | MIT-CMU CMU License MIT 59 | CNRI-Python CNRI Python License CNRI 60 | CNRI-Python-GPL-Compatible CNRI Python Open Source GPL Compatible License Agreement 61 | CPOL-1.02 Code Project Open License 1.02 62 | CDDL-1.0 Common Development and Distribution License 1.0 CDDL 63 | CDDL-1.1 Common Development and Distribution License 1.1 CDDL 64 | CPAL-1.0 Common Public Attribution License 1.0 CPAL 65 | CPL-1.0 Common Public License 1.0 CPL 66 | CATOSL-1.1 Computer Associates Trusted Open Source License 1.1 CATOSL 67 | Condor-1.1 Condor Public License v1.1 Condor 68 | CC-BY-1.0 Creative Commons Attribution 1.0 69 | CC-BY-2.0 Creative Commons Attribution 2.0 70 | CC-BY-2.5 Creative Commons Attribution 2.5 71 | CC-BY-3.0 Creative Commons Attribution 3.0 72 | CC-BY-4.0 Creative Commons Attribution 4.0 73 | CC-BY-ND-1.0 Creative Commons Attribution No Derivatives 1.0 74 | CC-BY-ND-2.0 Creative Commons Attribution No Derivatives 2.0 75 | CC-BY-ND-2.5 Creative Commons Attribution No Derivatives 2.5 76 | CC-BY-ND-3.0 Creative Commons Attribution No Derivatives 3.0 77 | CC-BY-ND-4.0 Creative Commons Attribution No Derivatives 4.0 78 | CC-BY-NC-1.0 Creative Commons Attribution Non Commercial 1.0 79 | CC-BY-NC-2.0 Creative Commons Attribution Non Commercial 2.0 80 | CC-BY-NC-2.5 Creative Commons Attribution Non Commercial 2.5 81 | CC-BY-NC-3.0 Creative Commons Attribution Non Commercial 3.0 82 | CC-BY-NC-4.0 Creative Commons Attribution Non Commercial 4.0 83 | CC-BY-NC-ND-1.0 Creative Commons Attribution Non Commercial No Derivatives 1.0 84 | CC-BY-NC-ND-2.0 Creative Commons Attribution Non Commercial No Derivatives 2.0 85 | CC-BY-NC-ND-2.5 Creative Commons Attribution Non Commercial No Derivatives 2.5 86 | CC-BY-NC-ND-3.0 Creative Commons Attribution Non Commercial No Derivatives 3.0 87 | CC-BY-NC-ND-4.0 Creative Commons Attribution Non Commercial No Derivatives 4.0 88 | CC-BY-NC-SA-1.0 Creative Commons Attribution Non Commercial Share Alike 1.0 89 | CC-BY-NC-SA-2.0 Creative Commons Attribution Non Commercial Share Alike 2.0 90 | CC-BY-NC-SA-2.5 Creative Commons Attribution Non Commercial Share Alike 2.5 91 | CC-BY-NC-SA-3.0 Creative Commons Attribution Non Commercial Share Alike 3.0 92 | CC-BY-NC-SA-4.0 Creative Commons Attribution Non Commercial Share Alike 4.0 93 | CC-BY-SA-1.0 Creative Commons Attribution Share Alike 1.0 94 | CC-BY-SA-2.0 Creative Commons Attribution Share Alike 2.0 95 | CC-BY-SA-2.5 Creative Commons Attribution Share Alike 2.5 96 | CC-BY-SA-3.0 Creative Commons Attribution Share Alike 3.0 97 | CC-BY-SA-4.0 Creative Commons Attribution Share Alike 4.0 98 | CC0-1.0 Creative Commons Zero v1.0 Universal CC0 99 | Crossword Crossword License Crossword 100 | CUA-OPL-1.0 CUA Office Public License v1.0 MPLv1.1 101 | Cube Cube License Cube 102 | D-FSL-1.0 Deutsche Freie Software Lizenz 103 | diffmark diffmark license diffmark 104 | WTFPL Do What The F*ck You Want To Public License WTFPL 105 | DOC DOC License DOC 106 | Dotseqn Dotseqn License Dotseqn 107 | DSDP DSDP License DSDP 108 | dvipdfm dvipdfm License dvipdfm 109 | EPL-1.0 Eclipse Public License 1.0 EPL 110 | eCos-2.0 eCos license version 2.0 eCos 111 | ECL-1.0 Educational Community License v1.0 ECL 1.0 112 | ECL-2.0 Educational Community License v2.0 ECL 2.0 113 | eGenix eGenix.com Public License 1.1.0 eGenix 114 | EFL-1.0 Eiffel Forum License v1.0 115 | EFL-2.0 Eiffel Forum License v2.0 EFL 2.0 116 | MIT-advertising Enlightenment License (e16) MIT with advertising 117 | MIT-enna enna License MIT 118 | Entessa Entessa Public License v1.0 Entessa 119 | ErlPL-1.1 Erlang Public License v1.1 ERPL 120 | EUDatagrid EU DataGrid Software License EU Datagrid 121 | EUPL-1.0 European Union Public License 1.0 122 | EUPL-1.1 European Union Public License 1.1 EUPL 1.1 123 | Eurosym Eurosym License Eurosym 124 | Fair Fair License Fair 125 | MIT-feh feh License MIT 126 | Frameworx-1.0 Frameworx Open License 1.0 127 | FTL Freetype Project License FTL 128 | FSFUL FSF Unlimited License FSFUL 129 | FSFULLR FSF Unlimited License (with License Retention) FSFULLR 130 | Giftware Giftware License Giftware 131 | GL2PS GL2PS License GL2PS 132 | Glulxe Glulxe License Glulxe 133 | AGPL-3.0 GNU Affero General Public License v3.0 AGPLv3 134 | GFDL-1.1 GNU Free Documentation License v1.1 135 | GFDL-1.2 GNU Free Documentation License v1.2 136 | GFDL-1.3 GNU Free Documentation License v1.3 137 | GPL-1.0 GNU General Public License v1.0 only GPLv1 138 | GPL-1.0+ GNU General Public License v1.0 or later GPL+ 139 | GPL-2.0 GNU General Public License v2.0 only GPLv2 140 | GPL-2.0+ GNU General Public License v2.0 or later GPLv2+ 141 | GPL-2.0-with-autoconf-exception GNU General Public License v2.0 w/Autoconf exception GPLv2 with exceptions 142 | GPL-2.0-with-bison-exception GNU General Public License v2.0 w/Bison exception GPLv2 with exceptions 143 | GPL-2.0-with-classpath-exception GNU General Public License v2.0 w/Classpath exception GPLv2 with exceptions 144 | GPL-2.0-with-font-exception GNU General Public License v2.0 w/Font exception GPLv2 with exceptions 145 | GPL-2.0-with-GCC-exception GNU General Public License v2.0 w/GCC Runtime Library exception GPLv2 with exceptions 146 | GPL-3.0 GNU General Public License v3.0 only GPLv3 147 | GPL-3.0+ GNU General Public License v3.0 or later GPLv3+ 148 | GPL-3.0-with-autoconf-exception GNU General Public License v3.0 w/Autoconf exception GPLv3 with exceptions 149 | GPL-3.0-with-GCC-exception GNU General Public License v3.0 w/GCC Runtime Library exception GPLv3 with exceptions 150 | LGPL-2.1 GNU Lesser General Public License v2.1 only LGPLv2 151 | LGPL-2.1+ GNU Lesser General Public License v2.1 or later LGPLv2+ 152 | LGPL-3.0 GNU Lesser General Public License v3.0 only LGPLv3 153 | LGPL-3.0+ GNU Lesser General Public License v3.0 or later LGPLv3+ 154 | LGPL-2.0 GNU Library General Public License v2 only LGPLv2 155 | LGPL-2.0+ GNU Library General Public License v2 or later LGPLv2+ 156 | gnuplot gnuplot License gnuplot 157 | gSOAP-1.3b gSOAP Public License v1.3b 158 | HaskellReport Haskell Language Report License HaskellReport 159 | HPND Historic Permission Notice and Disclaimer MIT 160 | IBM-pibs IBM PowerPC Initialization and Boot Software 161 | IPL-1.0 IBM Public License v1.0 IBM 162 | ImageMagick ImageMagick License ImageMagick 163 | iMatix iMatix Standard Function Library Agreement iMatix 164 | Imlib2 Imlib2 License Imlib2 165 | IJG Independent JPEG Group License IJG 166 | Intel-ACPI Intel ACPI Software License Agreement Intel ACPI 167 | Intel Intel Open Source License 168 | IPA IPA Font License 169 | ISC ISC License ISC 170 | JasPer-2.0 JasPer License JasPer 171 | JSON JSON License 172 | LPPL-1.3a LaTeX Project Public License 1.3a LPPL 173 | LPPL-1.0 LaTeX Project Public License v1.0 174 | LPPL-1.1 LaTeX Project Public License v1.1 175 | LPPL-1.2 LaTeX Project Public License v1.2 176 | LPPL-1.3c LaTeX Project Public License v1.3c 177 | Latex2e Latex2e License Latex2e 178 | BSD-3-Clause-LBNL Lawrence Berkeley National Labs BSD variant license LBNL BSD 179 | Leptonica Leptonica License Leptonica 180 | Libpng libpng License zlib 181 | libtiff libtiff License libtiff 182 | LPL-1.02 Lucent Public License v1.02 LPL 183 | LPL-1.0 Lucent Public License Version 1.0 LPL 184 | MakeIndex MakeIndex License MakeIndex 185 | MTLL Matrix Template Library License MTLL 186 | MS-PL Microsoft Public License MS-PL 187 | MS-RL Microsoft Reciprocal License MS-RL 188 | MirOS MirOS Licence MirOS 189 | MITNFA MIT +no-false-attribs license MITNFA 190 | MIT MIT License MIT 191 | Motosoto Motosoto License Motosoto 192 | MPL-1.0 Mozilla Public License 1.0 MPLv1.0 193 | MPL-1.1 Mozilla Public License 1.1 MPLv1.1 194 | MPL-2.0 Mozilla Public License 2.0 MPLv2.0 195 | MPL-2.0-no-copyleft-exception Mozilla Public License 2.0 (no copyleft exception) 196 | mpich2 mpich2 License MIT 197 | Multics Multics License 198 | Mup Mup License Mup 199 | NASA-1.3 NASA Open Source Agreement 1.3 200 | Naumen Naumen Public License Naumen 201 | NBPL-1.0 Net Boolean Public License v1 202 | NetCDF NetCDF license NetCDF 203 | NGPL Nethack General Public License NGPL 204 | NOSL Netizen Open Source License NOSL 205 | NPL-1.0 Netscape Public License v1.0 Netscape 206 | NPL-1.1 Netscape Public License v1.1 Netscape 207 | Newsletr Newsletr License Newsletr 208 | NLPL No Limit Public License NLPL 209 | Nokia Nokia Open Source License Nokia 210 | NPOSL-3.0 Non-Profit Open Software License 3.0 211 | Noweb Noweb License Noweb 212 | NRL NRL License BSD with advertising 213 | NTP NTP License 214 | Nunit Nunit License MIT with advertising 215 | OCLC-2.0 OCLC Research Public License 2.0 216 | ODbL-1.0 ODC Open Database License v1.0 217 | PDDL-1.0 ODC Public Domain Dedication & License 1.0 218 | OGTSL Open Group Test Suite License 219 | OLDAP-2.2.2 Open LDAP Public License 2.2.2 OpenLDAP 220 | OLDAP-1.1 Open LDAP Public License v1.1 OpenLDAP 221 | OLDAP-1.2 Open LDAP Public License v1.2 OpenLDAP 222 | OLDAP-1.3 Open LDAP Public License v1.3 OpenLDAP 223 | OLDAP-1.4 Open LDAP Public License v1.4 OpenLDAP 224 | OLDAP-2.0 Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B) OpenLDAP 225 | OLDAP-2.0.1 Open LDAP Public License v2.0.1 OpenLDAP 226 | OLDAP-2.1 Open LDAP Public License v2.1 OpenLDAP 227 | OLDAP-2.2 Open LDAP Public License v2.2 OpenLDAP 228 | OLDAP-2.2.1 Open LDAP Public License v2.2.1 OpenLDAP 229 | OLDAP-2.3 Open LDAP Public License v2.3 OpenLDAP 230 | OLDAP-2.4 Open LDAP Public License v2.4 OpenLDAP 231 | OLDAP-2.5 Open LDAP Public License v2.5 OpenLDAP 232 | OLDAP-2.6 Open LDAP Public License v2.6 OpenLDAP 233 | OLDAP-2.7 Open LDAP Public License v2.7 OpenLDAP 234 | OML Open Market License OML 235 | OPL-1.0 Open Public License v1.0 236 | OSL-1.0 Open Software License 1.0 OSL 1.0 237 | OSL-1.1 Open Software License 1.1 OSL 1.1 238 | OSL-2.0 Open Software License 2.0 OSL 2.0 239 | OSL-2.1 Open Software License 2.1 OSL 2.1 240 | OSL-3.0 Open Software License 3.0 OSL 3.0 241 | OLDAP-2.8 OpenLDAP Public License v2.8 OpenLDAP 242 | OpenSSL OpenSSL License OpenSSL 243 | PHP-3.0 PHP License v3.0 PHP 244 | PHP-3.01 PHP License v3.01 PHP 245 | Plexus Plexus Classworlds License Plexus 246 | PostgreSQL PostgreSQL License PostgreSQL 247 | psfrag psfrag License psfrag 248 | psutils psutils License psutils 249 | Python-2.0 Python License 2.0 Python 250 | QPL-1.0 Q Public License 1.0 QPL 251 | Qhull Qhull License Qhull 252 | Rdisc Rdisc License Rdisc 253 | RPSL-1.0 RealNetworks Public Source License v1.0 RPSL 254 | RPL-1.1 Reciprocal Public License 1.1 255 | RPL-1.5 Reciprocal Public License 1.5 256 | RHeCos-1.1 Red Hat eCos Public License v1.1 257 | RSCPL Ricoh Source Code Public License 258 | Ruby Ruby License Ruby 259 | SAX-PD Sax Public Domain Notice 260 | Saxpath Saxpath License Saxpath 261 | SCEA SCEA Shared Source License SCEA 262 | SWL Scheme Widget Library (SWL) Software License Agreement SWL 263 | SGI-B-1.0 SGI Free Software License B v1.0 264 | SGI-B-1.1 SGI Free Software License B v1.1 265 | SGI-B-2.0 SGI Free Software License B v2.0 MIT 266 | OFL-1.0 SIL Open Font License 1.0 267 | OFL-1.1 SIL Open Font License 1.1 268 | SimPL-2.0 Simple Public License 2.0 269 | Sleepycat Sleepycat License 270 | SNIA SNIA Public License 1.1 SNIA 271 | SMLNJ Standard ML of New Jersey License MIT 272 | StandardML-NJ Standard ML of New Jersey License MIT 273 | SugarCRM-1.1.3 SugarCRM Public License v1.1.3 274 | SISSL Sun Industry Standards Source License v1.1 SISSL 275 | SISSL-1.2 Sun Industry Standards Source License v1.2 276 | SPL-1.0 Sun Public License v1.0 277 | Watcom-1.0 Sybase Open Watcom Public License 1.0 278 | TCL TCL/TK License TCL 279 | Unlicense The Unlicense Unlicense 280 | TMate TMate Open Source License TMate 281 | TORQUE-1.1 TORQUE v2.5+ Software License v1.1 TORQUEv1.1 282 | TOSL Trusster Open Source License TOSL 283 | Unicode-TOU Unicode Terms of Use Unicode 284 | NCSA University of Illinois/NCSA Open Source License NCSA 285 | Vim Vim License Vim 286 | VOSTROM VOSTROM Public License for Open Source VOSTROM 287 | VSL-1.0 Vovida Software License v1.0 VSL 288 | W3C W3C Software Notice and License W3C 289 | Wsuipa Wsuipa License Wsuipa 290 | WXwindows wxWindows Library License wxWidgets 291 | Xnet X.Net License 292 | X11 X11 License MIT 293 | Xerox Xerox License Xerox 294 | XFree86-1.1 XFree86 License 1.1 295 | xinetd xinetd License xinetd 296 | xpp XPP License xpp 297 | XSkat XSkat License XSkat 298 | YPL-1.0 Yahoo! Public License v1.0 299 | YPL-1.1 Yahoo! Public License v1.1 YPLv1.1 300 | Zed Zed License Zed 301 | Zend-2.0 Zend License v2.0 Zend 302 | Zimbra-1.3 Zimbra Public License v1.3 303 | Zlib zlib License zlib 304 | zlib-acknowledgement zlib/libpng License with Acknowledgement zlib with acknowledgement 305 | ZPL-1.1 Zope Public License 1.1 306 | ZPL-2.0 Zope Public License 2.0 ZPLv2.0 307 | ZPL-2.1 Zope Public License 2.1 ZPLv2.1 308 | -------------------------------------------------------------------------------- /path.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_path_isReadableFilePath() 6 | { 7 | local filePath="$1" 8 | 9 | if [ ! -e "$filePath" ]; then 10 | return 1 11 | fi 12 | 13 | if [ ! -f "$filePath" ]; then 14 | return 1 15 | fi 16 | 17 | if [ -r "$filePath" ]; then 18 | return 0 19 | fi 20 | 21 | return 1 22 | } 23 | 24 | core_path_isReadableNonEmptyFilePath() 25 | { 26 | local filePath="$1" 27 | 28 | core_path_isReadableFilePath "$filePath" 29 | 30 | if [ -s "$filePath" ]; then 31 | return 0 32 | fi 33 | 34 | return 1 35 | } 36 | 37 | core_path_isReadableNonEmptyExecutableFilePath() 38 | { 39 | local filePath="$1" 40 | 41 | core_path_isReadableNonEmptyFilePath "$filePath" 42 | 43 | if [ -x "$filePath" ]; then 44 | return 0 45 | fi 46 | 47 | return 1 48 | } 49 | 50 | core_path_isReadableAndSearchableFolderPath() 51 | { 52 | local folderPath="$1" 53 | 54 | if [ ! -e "$folderPath" ]; then 55 | return 1 56 | fi 57 | 58 | if [ ! -d "$folderPath" ]; then 59 | return 1 60 | fi 61 | 62 | if [ ! -r "$folderPath" ]; then 63 | return 1 64 | fi 65 | 66 | if [ -x "$folderPath" ]; then 67 | return 0 68 | fi 69 | 70 | return 1 71 | } 72 | 73 | core_path_isReadableAndSearchableAndWritableFolderPath() 74 | { 75 | core_path_isReadableAndSearchableFolderPath "$1" 76 | 77 | local folderPath="$1" 78 | 79 | if [ -w "$folderPath" ]; then 80 | return 0 81 | fi 82 | 83 | return 1 84 | } 85 | -------------------------------------------------------------------------------- /pipefail.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | # Original Copyright (c) 2003-2005, Joe Halpin 6 | # Modified from http://cfajohnson.com/shell/cus-faq-2.html#Q11 7 | # Original permissively licensed 8 | # Modifications Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 9 | # Uses the file descriptors 3 and 4 10 | # Run as com1 \| com2 \| com3 11 | core_pipefail_execute() 12 | { 13 | _core_pipefail_execute_unsetPipestatusVariablesFromPreviousRun 14 | 15 | local index=1 16 | local pipelineCommand='' 17 | local k=1 18 | local l='' 19 | local a='' 20 | for a in "$@" 21 | do 22 | if [ "$a" = '|' ]; then 23 | pipelineCommand="$pipelineCommand { $l "'3>&- 24 | echo "core_pipefail_PIPESTATUS_'$index'=$?" >&3 25 | } 4>&- |' 26 | index=$((index + 1)) 27 | l='' 28 | else 29 | l="$l \"\$$k\"" 30 | fi 31 | k=$((k + 1)) 32 | done 33 | pipelineCommand="$pipelineCommand $l"' 3>&- >&4 4>&- 34 | echo "core_pipefail_PIPESTATUS_'$index'=$?"' 35 | 36 | core_message DEBUG "About to execute pipeline command: '$pipelineCommand'" 37 | 38 | exec 4>&1 39 | eval "$(exec 3>&1; eval "$pipelineCommand")" 40 | exec 4>&- 41 | 42 | local exitCode 43 | _core_pipefail_execute_setPipestatusVariablesAndExitCode 44 | return $exitCode 45 | } 46 | 47 | _core_pipefail_execute_unsetPipestatusVariablesFromPreviousRun() 48 | { 49 | local index=1 50 | while core_variable_isSet core_pipefail_PIPESTATUS_$index 51 | do 52 | core_variable_unset core_pipefail_PIPESTATUS_$index 53 | index=$((index + 1)) 54 | done 55 | } 56 | 57 | _core_pipefail_execute_setPipestatusVariablesAndExitCode() 58 | { 59 | local index=1 60 | local core_variable_indirectValue_result 61 | while core_variable_isSet core_pipefail_PIPESTATUS_$index 62 | do 63 | core_variable_indirectValue core_pipefail_PIPESTATUS_$index 64 | if [ $core_variable_indirectValue_result -ne 0 ]; then 65 | exitCode=1 66 | return 0 67 | fi 68 | index=$((index + 1)) 69 | done 70 | } 71 | -------------------------------------------------------------------------------- /snippet.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core base64/decode variable temporaryFiles 6 | 7 | # Unfortunately, strips trailing LFs 8 | core_dependency_requires '*' cat 9 | core_snippet_raw_encoder() 10 | { 11 | # "$(>"$snippetFilePath" 21 | else 22 | printf '%s' "$core_variable_indirectValue_result" >"$snippetFilePath" 23 | fi 24 | } 25 | 26 | # Different base64 implementations wrap differently and with different switches 27 | core_dependency_requires '*' base64 tr 28 | core_snippet_base64_encoder() 29 | { 30 | _core_snippet_embeddedData_${snippetName}="$(base64 "$snippetFilePath" | tr -d '\n')" 31 | } 32 | 33 | core_snippet_base64_decoder() 34 | { 35 | core_base64_decode_string "$(core_variable_indirectValue _core_snippet_embeddedData_${snippetName})" "$snippetFilePath" "$snippetAppend" '+' '/' 36 | } 37 | 38 | core_usesIn core variable 39 | core_snippet_embed() 40 | { 41 | local codecName="$1" 42 | shift 1 43 | 44 | local encoder="core_snippet_${codecName}_encoder" 45 | 46 | local snippetName 47 | local snippetFilePath 48 | for snippetName in "$@" 49 | do 50 | if core_variable_isSet _core_snippet_embeddedData_${snippetName}; then 51 | continue 52 | fi 53 | 54 | snippetFilePath="$_program_libPath"/"$core_libraryName"/"${_program_namespace}"/"$snippetName".snippet 55 | if ! core_path_isReadableNonEmptyFilePath "$snippetFilePath"; then 56 | core_exitError $core_commandLine_exitCode_SOFTWARE "Snippet '$snippetName' does not exist as a readable, non-empty file at '$snippetFilePath'" 57 | fi 58 | 59 | ${encoder} 60 | core_dependency_declares _core_snippet_embeddedData_${snippetName} 61 | 62 | core_variable_setVariable _core_snippet_embeddedCodec_${snippetName} $codecName 63 | core_dependency_declares _core_snippet_embeddedCodec_${snippetName} 64 | done 65 | } 66 | 67 | core_snippet_retrieve() 68 | { 69 | local snippetName="$1" 70 | local snippetAppend="$2" 71 | local snippetFilePath="$3" 72 | local core_variable_indirectValue_result 73 | local codec 74 | local decoder 75 | 76 | core_variable_indirectValue _core_snippet_embeddedCodec_${snippetName} 77 | codec="$core_variable_indirectValue_result" 78 | decoder="core_snippet_${codec}_decoder" 79 | ${decoder} 80 | } 81 | 82 | core_dependency_requires '*' cat rm 83 | core_snippet_retrieveAndSourceAsHereDoc() 84 | { 85 | local snippetName="$1" 86 | 87 | local TMP_FILE 88 | core_temporaryFiles_newFileToRemoveOnExit 89 | local snippetFilePath="$TMP_FILE" 90 | 91 | printf '%s\n' 'cat <"$snippetFilePath" 92 | core_snippet_retrieve "$snippetName" yes "$snippetFilePath" 93 | printf '\nEOF' >>"$snippetFilePath" 94 | 95 | . "$snippetFilePath" 96 | rm "$snippetFilePath" || true 97 | } 98 | -------------------------------------------------------------------------------- /temporaryFiles.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core trap 6 | core_usesIn core/variable array 7 | core_usesIn core validate 8 | 9 | core_temporaryFiles_initialise() 10 | { 11 | core_trap_addOnCleanUp core_temporaryFiles_removeAll 12 | 13 | if core_variable_isUnset TMPDIR; then 14 | # Typically on Windows; Cygwin prefers TMP and re-writes to an Unix path 15 | # Git-Bash et al use TMP and TEMP and may be DOS-paths which they *should* convert 16 | if core_variable_isSet TMP; then 17 | TMPDIR="$TMP" 18 | elif core_variable_isSet TEMP; then 19 | TMPDIR="$TEMP" 20 | else 21 | core_message NOTICE "Defaulting TMPDIR to '/tmp'" 22 | TMPDIR='/tmp' 23 | fi 24 | # Mac OS X 25 | elif core_variable_endsWith "$TMPDIR" '/'; then 26 | TMPDIR="$(core_variable_allButLast "$TMPDIR")" 27 | fi 28 | 29 | core_validate_folderPathReadableAndSearchableAndWritable $core_commandLine_exitCode_CONFIG "environment variable (or default, '/tmp')" 'TMPDIR' "$TMPDIR" 30 | 31 | # we don't use tempfile, as it only creates files, not folders and isn't common 32 | 33 | # mktemp doesn't exist on AIX or Solaris, and doesn't create files w/o -c on HP-UX 34 | # This logic won't work on HP-UX. 35 | if core_compatibility_whichNoOutput mktemp; then 36 | 37 | core_temporaryFiles_newFileToRemoveOnExit() 38 | { 39 | local umaskOriginal="$(umask)" 40 | umask 077 41 | 42 | # was mktemp -t "$_program_name".XXXXXXXXXXXX 43 | # still won't work for HP-UX, as -c not specified. That said, HP-UX mktemp doesn't seem to be very safe (http://nixdoc.net/man-pages/HP-UX/man1/mktemp.1.html) 44 | TMP_FILE="$(mktemp "$TMPDIR"/"$_program_name".XXXXXXXXXXXX)" || core_exitError $core_commandLine_exitCode_CANTCREAT "Could not create a temporary file" 45 | core_variable_array_append _core_temporaryFiles_filesToRemoveOnExit "$TMP_FILE" 46 | 47 | umask "$umaskOriginal" 48 | } 49 | 50 | core_temporaryFiles_newFolderToRemoveOnExit() 51 | { 52 | local umaskOriginal="$(umask)" 53 | umask 077 54 | 55 | # was mktemp -d -t "$_program_name".XXXXXXXXXXXX 56 | # still won't work for HP-UX, as -c not specified. That said, HP-UX mktemp doesn't seem to be very safe 57 | TMP_FOLDER="$(mktemp -d "$TMPDIR"/"$_program_name".XXXXXXXXXXXX)" || core_exitError $core_commandLine_exitCode_CANTCREAT "Could not create a temporary folder" 58 | core_variable_array_append _core_temporaryFiles_filesToRemoveOnExit "$TMP_FOLDER" 59 | 60 | umask "$umaskOriginal" 61 | } 62 | 63 | return 0 64 | fi 65 | 66 | # There are other sources of randomness, but it starts to get silly (eg http://mywiki.wooledge.org/BashFAQ/062) 67 | 68 | if core_variable_isSet RANDOM; then 69 | 70 | core_message WARN "Your system doesn't have mktemp - we're creating temporary files INSECURELY in '$TMPDIR' using process id and 'RANDOM'" 71 | 72 | core_temporaryFiles_newFileToRemoveOnExit() 73 | { 74 | local umaskOriginal="$(umask)" 75 | umask 077 76 | 77 | TMP_FILE="$TMPDIR"/"${_program_name}.file.$$.${RANDOM}" 78 | printf '' >"$TMP_FILE" || core_exitError $core_commandLine_exitCode_CANTCREAT "Could not create a temporary file" 79 | core_variable_array_append _core_temporaryFiles_filesToRemoveOnExit "$TMP_FILE" 80 | 81 | umask "$umaskOriginal" 82 | } 83 | 84 | core_temporaryFiles_newFolderToRemoveOnExit() 85 | { 86 | local umaskOriginal="$(umask)" 87 | umask 077 88 | 89 | TMP_FOLDER="$TMPDIR"/"${_program_name}.folder.$$.${RANDOM}" 90 | mkdir -m 0700 -p "$TMP_FOLDER" || core_exitError $core_commandLine_exitCode_CANTCREAT "Could not create a temporary folder" 91 | core_variable_array_append _core_temporaryFiles_filesToRemoveOnExit "$TMP_FOLDER" 92 | 93 | umask "$umaskOriginal" 94 | } 95 | 96 | return 0 97 | fi 98 | 99 | if core_variable_isSet HOME; then 100 | 101 | if ! core_path_isReadableAndSearchableAndWritableFolderPath "$HOME"; then 102 | core_exitError $core_commandLine_exitCode_CANTCREAT "Your shell doesn't have RANDOM, mktemp isn't available and your HOME '$HOME' isn't writable. We've got no where left to put temporary files." 103 | fi 104 | 105 | TMPDIR="$HOME"/"$_program_name/$$" 106 | 107 | core_message WARN "Your shell doesn't have RANDOM, and mktemp isn't available. - we're creating temporary files beneath your HOME at '$TMPDIR'" 108 | 109 | rm -rf "$TMPDIR" 2>/dev/null || true 110 | mkdir -m 0700 "$TMPDIR" || core_exitError $core_commandLine_exitCode_CANTCREAT "Could not create a temporary folder" 111 | core_variable_array_append _core_temporaryFiles_filesToRemoveOnExit "$TMPDIR" 112 | 113 | _core_temporaryFiles_fileCounter=0 114 | core_temporaryFiles_newFileToRemoveOnExit() 115 | { 116 | local umaskOriginal="$(umask)" 117 | umask 077 118 | 119 | TMP_FILE="$TMPDIR"/file."$_core_temporaryFiles_fileCounter" 120 | _core_temporaryFiles_fileCounter=$((_core_temporaryFiles_fileCounter+1)) 121 | printf '' >"$TMP_FILE" || core_exitError $core_commandLine_exitCode_CANTCREAT "Could not create a temporary file" 122 | 123 | umask "$umaskOriginal" 124 | } 125 | 126 | _core_temporaryFiles_folderCounter=0 127 | core_temporaryFiles_newFolderToRemoveOnExit() 128 | { 129 | local umaskOriginal="$(umask)" 130 | umask 077 131 | 132 | TMP_FOLDER="$TMPDIR"/folder."$_core_temporaryFiles_folderCounter" 133 | _core_temporaryFiles_folderCounter=$((_core_temporaryFiles_folderCounter+1)) 134 | mkdir -m 0700 -p "$TMP_FOLDER" || core_exitError $core_commandLine_exitCode_CANTCREAT "Could not create a temporary folder" 135 | 136 | umask "$umaskOriginal" 137 | } 138 | 139 | return 0 140 | fi 141 | 142 | core_exitError $core_commandLine_exitCode_CANTCREAT "Your shell doesn't have RANDOM, mktemp isn't available and your HOME isn't set. We've got no where left to put temporary files." 143 | } 144 | core_functions_register _core_functions core_temporaryFiles_initialise 145 | 146 | core_dependency_requires '*' rm 147 | _core_temporaryFiles_removeAll_callback() 148 | { 149 | local pathToDelete 150 | for pathToDelete in "$@" 151 | do 152 | if [ ! -e "$pathToDelete" ]; then 153 | continue 154 | fi 155 | 156 | if rm -r -f "$pathToDelete" 1>/dev/null 2>/dev/null; then 157 | continue 158 | fi 159 | 160 | if core_compatibility_whichNoOutput sudo; then 161 | sudo -p "Please enter the password for %p to forcibly rm the temporary path '$pathToDelete': " rm -r -f "$pathToDelete" || core_message WARN "Could not forcibly delete temporary path '$pathToDelete'" 162 | fi 163 | done 164 | } 165 | 166 | core_temporaryFiles_removeAll() 167 | { 168 | if core_variable_array_isSet _core_temporaryFiles_filesToRemoveOnExit; then 169 | core_variable_array_passToFunctionAsArguments _core_temporaryFiles_filesToRemoveOnExit _core_temporaryFiles_removeAll_callback 170 | fi 171 | } 172 | -------------------------------------------------------------------------------- /trap.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core/variable array 6 | 7 | core_trap_initialise() 8 | { 9 | local trapNames='EXIT|HUP|INT|QUIT|ABRT|PIPE|TERM|TSTP|USR1|USR2' 10 | local trapName 11 | local IFS='|' 12 | for trapName in $trapNames 13 | do 14 | trap "_core_trap_executeOnTrap $trapName" "$trapName" 15 | done 16 | } 17 | core_functions_register _core_functions core_trap_initialise 18 | 19 | core_trap_addOnCleanUp() 20 | { 21 | #core_trap_addHandler "$1" EXIT INT TERM ABRT QUIT PIPE 22 | core_trap_addHandler "$1" EXIT INT TERM ABRT QUIT 23 | } 24 | 25 | _core_trap_executeOnTrap() 26 | { 27 | local trapName="$1" 28 | local arrayName="core_trap_handlers_${trapName}" 29 | 30 | if core_variable_array_isUnset "$arrayName"; then 31 | return 0 32 | fi 33 | core_variable_array_iterateAsCallbacks "$arrayName" 34 | } 35 | 36 | core_trap_addHandler() 37 | { 38 | local handler="$1" 39 | shift 1 40 | 41 | local trapName 42 | for trapName in "$@" 43 | do 44 | case "$trapName" in 45 | 46 | # DEBUG|ERR|RETURN are not supported 47 | 48 | EXIT|HUP|INT|QUIT|ABRT|PIPE|TERM|TSTP|USR1|USR2) 49 | : 50 | ;; 51 | 52 | *) 53 | core_exitError $core_commandLine_exitCode_SOFTWARE "Unrecognised or unsupported trap '$trapName'" 54 | ;; 55 | 56 | esac 57 | done 58 | 59 | for trapName in "$@" 60 | do 61 | core_variable_array_append core_trap_handlers_${trapName} "$handler" 62 | done 63 | } 64 | -------------------------------------------------------------------------------- /umask.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | # Done so scripts can rely on a sane value 6 | core_umask_setDefault() 7 | { 8 | umask 022 9 | } 10 | -------------------------------------------------------------------------------- /validate.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_validate_exit() 6 | { 7 | local message="$1" 8 | if [ $code -eq $core_commandLine_exitCode_USAGE ]; then 9 | core_commandLine_exitBadCommandLine "$message" 10 | else 11 | core_exitError $code "$message" 12 | fi 13 | } 14 | 15 | core_validate_pathNotEmpty() 16 | { 17 | local code=$1 18 | local category="$2" 19 | local name="$3" 20 | local value="$4" 21 | 22 | if [ -z "$value" ]; then 23 | core_validate_exit "The $category '$name' specifies a path '$value' which is empty" 24 | fi 25 | } 26 | 27 | core_validate_folderPathReadableAndSearchable() 28 | { 29 | core_validate_pathNotEmpty "$@" 30 | 31 | local code=$1 32 | local category="$2" 33 | local name="$3" 34 | local value="$4" 35 | 36 | local messageFragment="The $category '$name' specifies a path '$value' which" 37 | if [ ! -e "$value" ]; then 38 | core_validate_exit "$messageFragment does not exist" 39 | fi 40 | if [ ! -d "$value" ]; then 41 | core_validate_exit "$messageFragment is not a directory" 42 | fi 43 | if [ ! -r "$value" ]; then 44 | core_validate_exit "$messageFragment is not a readable directory" 45 | fi 46 | if [ ! -x "$value" ]; then 47 | core_validate_exit "$messageFragment is not a searchable directory" 48 | fi 49 | } 50 | 51 | core_validate_folderPathReadableAndSearchableAndWritable() 52 | { 53 | core_validate_folderPathReadableAndSearchable "$@" 54 | 55 | local code=$1 56 | local category="$2" 57 | local name="$3" 58 | local value="$4" 59 | 60 | if [ ! -w "$value" ]; then 61 | core_validate_exit "The $category '$name' specifies a path '$value' which is not a writable directory" 62 | fi 63 | } 64 | 65 | core_validate_parentFolderPathReadableAndSearchable() 66 | { 67 | core_validate_pathNotEmpty "$@" 68 | 69 | local code=$1 70 | local category="$2" 71 | local name="$3" 72 | local value="$4" 73 | 74 | if [ "$value" = '/' ]; then 75 | core_validate_exit "The $category '$name' specifies a path '$value' with no parent" 76 | fi 77 | if [ "$(core_compatibility_basename "$value")" = "$value" ]; then 78 | local parentPath="$(pwd)"/.. 79 | else 80 | local parentPath="$(core_compatibility_dirname "$value")" 81 | fi 82 | 83 | local messageFragment="The $category '$name' specifies a path '$value' with a parent which" 84 | if [ ! -e "$parentPath" ]; then 85 | core_validate_exit "$messageFragment does not exist" 86 | fi 87 | if [ ! -d "$parentPath" ]; then 88 | core_validate_exit "$messageFragment is not a directory" 89 | fi 90 | if [ ! -r "$parentPath" ]; then 91 | core_validate_exit "$messageFragment is not a readable directory" 92 | fi 93 | if [ ! -x "$parentPath" ]; then 94 | core_validate_exit "$messageFragment is not a searchable directory" 95 | fi 96 | } 97 | 98 | core_validate_parentFolderPathReadableAndSearchableAndWritable() 99 | { 100 | core_validate_parentFolderPathReadableAndSearchable "$@" 101 | 102 | local code=$1 103 | local category="$2" 104 | local name="$3" 105 | local value="$4" 106 | 107 | if [ "$value" = '/' ]; then 108 | core_validate_exit "The $category '$name' specifies a path '$value' with no parent" 109 | fi 110 | if [ "$(core_compatibility_basename "$value")" = "$value" ]; then 111 | local parentPath="$(pwd)"/.. 112 | else 113 | local parentPath="$(core_compatibility_dirname "$value")" 114 | fi 115 | 116 | if [ ! -w "$parentPath" ]; then 117 | core_validate_exit "The $category '$name' specifies a path '$value' with parent which is not a writable directory" 118 | fi 119 | } 120 | 121 | core_validate_folderPathIsReadableAndSearchableAndWritableOrCanBeCreated() 122 | { 123 | local value="$4" 124 | 125 | if [ -d "$value" ]; then 126 | core_validate_folderPathReadableAndSearchableAndWritable "$@" 127 | else 128 | core_validate_parentFolderPathReadableAndSearchableAndWritable "$@" 129 | fi 130 | } 131 | 132 | core_validate_filePathReadable() 133 | { 134 | core_validate_pathNotEmpty "$@" 135 | 136 | local code=$1 137 | local category="$2" 138 | local name="$3" 139 | local value="$4" 140 | 141 | local messageFragment="The $category '$name' specifies a path '$value' which" 142 | if [ ! -e "$value" ]; then 143 | core_validate_exit "$messageFragment does not exist" 144 | fi 145 | if [ ! -f "$value" ]; then 146 | core_validate_exit "$messageFragment is not a file" 147 | fi 148 | if [ ! -r "$value" ]; then 149 | core_validate_exit "$messageFragment is not a readable file" 150 | fi 151 | } 152 | 153 | core_validate_filePathReadableAndExecutable() 154 | { 155 | core_validate_filePathReadable "$@" 156 | 157 | local code=$1 158 | local category="$2" 159 | local name="$3" 160 | local value="$4" 161 | 162 | local messageFragment="The $category '$name' specifies a path '$value' which" 163 | if [ ! -x "$value" ]; then 164 | core_validate_exit "$messageFragment is not an executable file" 165 | fi 166 | } 167 | 168 | core_validate_filePathReadableAndExecutableAndNotEmpty() 169 | { 170 | core_validate_filePathReadableAndExecutable "$@" 171 | 172 | local code=$1 173 | local category="$2" 174 | local name="$3" 175 | local value="$4" 176 | 177 | if [ ! -s "$value" ]; then 178 | core_validate_exit "The $category '$name' specifies a path which is an empty file" 179 | fi 180 | } 181 | 182 | core_validate_socketPathReadableAndWritable() 183 | { 184 | core_validate_pathNotEmpty "$@" 185 | 186 | local code=$1 187 | local category="$2" 188 | local name="$3" 189 | local value="$4" 190 | 191 | local messageFragment="The $category '$name' specifies a path '$value' which" 192 | if [ ! -e "$value" ]; then 193 | core_validate_exit "$messageFragment does not exist" 194 | fi 195 | if [ ! -S "$value" ]; then 196 | core_validate_exit "$messageFragment is not a socket" 197 | fi 198 | if [ ! -r "$value" ]; then 199 | core_validate_exit "$messageFragment is not a readable socket" 200 | fi 201 | if [ ! -x "$value" ]; then 202 | core_validate_exit "$messageFragment is not an executable socket" 203 | fi 204 | } 205 | 206 | core_validate_characterDeviceFileReadableAndWritable() 207 | { 208 | core_validate_pathNotEmpty "$@" 209 | 210 | local code=$1 211 | local category="$2" 212 | local name="$3" 213 | local value="$4" 214 | 215 | local messageFragment="The $category '$name' specifies a path '$value' which" 216 | if [ ! -e "$value" ]; then 217 | core_validate_exit "$messageFragment does not exist" 218 | fi 219 | if [ ! -c "$value" ]; then 220 | core_validate_exit "$messageFragment is not a character device file" 221 | fi 222 | if [ ! -r "$value" ]; then 223 | core_validate_exit "$messageFragment is not a readable character device file" 224 | fi 225 | if [ ! -x "$value" ]; then 226 | core_validate_exit "$messageFragment is not an executable character device file" 227 | fi 228 | } 229 | 230 | core_validate_isBoolean() 231 | { 232 | local code=$1 233 | local category="$2" 234 | local name="$3" 235 | local value="$4" 236 | 237 | set +e 238 | core_variable_isTrue "$value" 239 | local exitCode=$? 240 | set -e 241 | 242 | if [ $exitCode -eq 2 ]; then 243 | core_validate_exit "The $category '$name' should be yes or no, not '$value'" 244 | fi 245 | } 246 | 247 | # From https://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash 248 | # See comments by Gilles for negative number tests 249 | core_validate_isUnsignedInteger() 250 | { 251 | local code=$1 252 | local category="$2" 253 | local name="$3" 254 | local value="$4" 255 | 256 | case "$value" in 257 | ''|*[!0-9]*) 258 | core_validate_exit "The $category '$name' should be an unsigned integer, not '$value'" 259 | ;; 260 | 261 | *) 262 | : 263 | ;; 264 | esac 265 | } 266 | 267 | core_validate_nonDynamicPort() 268 | { 269 | local code=$1 270 | local category="$2" 271 | local name="$3" 272 | local value="$4" 273 | 274 | core_validate_isUnsignedInteger $code "$category" "$name" "$value" 275 | if [ $value -lt 1 ]; then 276 | core_validate_exit "The $category '$name' should be between 1 and 65535, not '$value'" 277 | fi 278 | if [ $value -gt 65535 ]; then 279 | core_validate_exit "The $category '$name' should be between 1 and 65535, not '$value'" 280 | fi 281 | } 282 | -------------------------------------------------------------------------------- /variable/array.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_usesIn core variable 6 | 7 | core_init_defines core_variable_array_delimiter 8 | 9 | core_variable_array_warning() 10 | { 11 | if [ "$core_init_preferred_shell" = 'sh' ]; then 12 | if core_variable_isSet BASH_VERSINFO; then 13 | if [ "$BASH_VERSINFO" -eq 3 ]; then 14 | core_message NOTICE "There's a horrible bug in bash 3, which when run as sh, that treats 'local variableName' as being set to empty, not as unset. We have to support bash 3 for Mac OS X and MinGW." 15 | core_message NOTICE "There's a horrible bug in bash 3, which when run as sh, that doesn't like IFS='\001'." 16 | fi 17 | fi 18 | fi 19 | } 20 | 21 | core_variable_array_initialise() 22 | { 23 | local variableName="$1" 24 | local variableNameInitialised="${variableName}_initialised" 25 | 26 | if core_variable_isSet "$variableNameInitialised"; then 27 | 28 | local core_variable_indirectValue_result 29 | core_variable_indirectValue "$variableNameInitialised" 30 | 31 | if [ -n "$core_variable_indirectValue_result" ]; then 32 | return 0 33 | fi 34 | fi 35 | 36 | core_variable_setVariable "$variableName" '' 37 | core_variable_setVariable "$variableNameInitialised" 0 38 | } 39 | 40 | core_variable_array_unset() 41 | { 42 | local variableName="$1" 43 | local variableNameInitialised="${variableName}_initialised" 44 | core_variable_unset "$variableName" 45 | core_variable_unset "$variableNameInitialised" 46 | } 47 | 48 | core_variable_array_isSet() 49 | { 50 | local variableName="$1" 51 | local variableNameInitialised="${variableName}_initialised" 52 | 53 | if core_variable_isSet "$variableNameInitialised"; then 54 | 55 | local core_variable_indirectValue_result 56 | core_variable_indirectValue "$variableNameInitialised" 57 | 58 | if [ ${core_variable_indirectValue_result} -gt 0 ]; then 59 | return 0 60 | else 61 | return 1 62 | fi 63 | fi 64 | 65 | return 1 66 | } 67 | 68 | core_variable_array_isUnset() 69 | { 70 | ! core_variable_array_isSet "$1" 71 | } 72 | 73 | core_variable_array_append() 74 | { 75 | local variableName="$1" 76 | shift 1 77 | 78 | local argument 79 | for argument in "$@" 80 | do 81 | if core_variable_array_isUnset "$variableName"; then 82 | core_variable_array_initialise "$variableName" 83 | core_variable_setVariable "$variableName" "$argument" 84 | core_variable_setVariable "${variableName}_initialised" 1 85 | else 86 | core_variable_indirectValue "${variableName}_initialised" 87 | core_variable_setVariable "${variableName}_initialised" $((core_variable_indirectValue_result+1)) 88 | core_variable_indirectValue "$variableName" 89 | core_variable_setVariable "$variableName" "${core_variable_indirectValue_result}$core_variable_array_delimiter${argument}" 90 | fi 91 | done 92 | } 93 | 94 | core_variable_array_appendUniquely() 95 | { 96 | local variableName="$1" 97 | shift 1 98 | 99 | local argument 100 | for argument in "$@" 101 | do 102 | if ! core_variable_array_contains "$variableName" "$argument"; then 103 | core_variable_array_append "$variableName" "$argument" 104 | fi 105 | done 106 | } 107 | 108 | core_variable_array_length() 109 | { 110 | local variableName="$1" 111 | shift 1 112 | 113 | local core_variable_indirectValue_result 114 | core_variable_indirectValue "${variableName}_initialised" 115 | printf '%s' $core_variable_indirectValue_result 116 | } 117 | 118 | _core_variable_array_isEmpty() 119 | { 120 | local core_variable_indirectValue_result 121 | core_variable_indirectValue "${variableName}_initialised" 122 | [ $core_variable_indirectValue_result -eq 0 ] 123 | } 124 | 125 | core_variable_array_isEmpty() 126 | { 127 | local variableName="$1" 128 | _core_variable_array_isEmpty 129 | } 130 | 131 | core_variable_array_at() 132 | { 133 | local variableName="$1" 134 | local index=$2 135 | 136 | local core_variable_indirectValue_result 137 | core_variable_indirectValue "$variableName" 138 | 139 | local originalIFS="$IFS" 140 | local IFS="$core_variable_array_delimiter" 141 | set -- $core_variable_indirectValue_result 142 | IFS="$originalIFS" 143 | 144 | eval "core_variable_array_index_element=\"\$${index}\"" 145 | } 146 | 147 | core_variable_array_string() 148 | { 149 | local variableName="$1" 150 | local separator="$2" 151 | 152 | if _core_variable_array_isEmpty; then 153 | return 0 154 | fi 155 | 156 | local core_variable_indirectValue_result 157 | core_variable_indirectValue "$variableName" 158 | 159 | local count=0 160 | local originalIFS="$IFS" 161 | local IFS="$core_variable_array_delimiter" 162 | for core_variable_array_element in $core_variable_indirectValue_result 163 | do 164 | IFS="$originalIFS" 165 | if [ $count -eq 0 ]; then 166 | printf '%s' "$core_variable_array_element" 167 | else 168 | printf '%s%s' "$separator" "$core_variable_array_element" 169 | fi 170 | count=$((count+1)) 171 | done 172 | IFS="$originalIFS" 173 | } 174 | 175 | # Does not allow passing any other arguments, though 176 | core_variable_array_passToFunctionAsArguments() 177 | { 178 | local variableName="$1" 179 | local function="$2" 180 | shift 2 181 | if [ $# -ne 0 ]; then 182 | core_exitError $core_commandLine_exitCode_SOFTWARE "Only varargs from array are allowed" 183 | fi 184 | 185 | if _core_variable_array_isEmpty; then 186 | "$function" 187 | return 0 188 | fi 189 | 190 | local core_variable_indirectValue_result 191 | core_variable_indirectValue "$variableName" 192 | 193 | local originalIFS="$IFS" 194 | local IFS="$core_variable_array_delimiter" 195 | set -- $core_variable_indirectValue_result 196 | IFS="$originalIFS" 197 | 198 | "$function" "$@" 199 | } 200 | 201 | core_variable_array_iterate() 202 | { 203 | local variableName="$1" 204 | local callback="$2" 205 | shift 2 206 | 207 | if _core_variable_array_isEmpty; then 208 | return 0 209 | fi 210 | 211 | local core_variable_indirectValue_result 212 | core_variable_indirectValue "$variableName" 213 | 214 | local originalIFS="$IFS" 215 | local IFS="$core_variable_array_delimiter" 216 | local core_variable_array_element 217 | for core_variable_array_element in $core_variable_indirectValue_result 218 | do 219 | IFS="$originalIFS" 220 | $callback "$@" 221 | done 222 | IFS="$originalIFS" 223 | } 224 | 225 | core_variable_array_iterateAsCallbacks() 226 | { 227 | local variableName="$1" 228 | shift 1 229 | 230 | if _core_variable_array_isEmpty; then 231 | return 0 232 | fi 233 | 234 | local core_variable_indirectValue_result 235 | core_variable_indirectValue "$variableName" 236 | 237 | local originalIFS="$IFS" 238 | local IFS="$core_variable_array_delimiter" 239 | local callback 240 | for callback in $core_variable_indirectValue_result 241 | do 242 | IFS="$originalIFS" 243 | "$callback" "$@" 244 | done 245 | IFS="$originalIFS" 246 | } 247 | 248 | core_variable_array_iterateAsCallbacksShortcut() 249 | { 250 | local variableName="$1" 251 | shift 1 252 | 253 | if _core_variable_array_isEmpty; then 254 | return 1 255 | fi 256 | 257 | local core_variable_indirectValue_result 258 | core_variable_indirectValue "$variableName" 259 | 260 | local originalIFS="$IFS" 261 | local IFS="$core_variable_array_delimiter" 262 | local callback 263 | for callback in $core_variable_indirectValue_result 264 | do 265 | IFS="$originalIFS" 266 | if "$callback" "$@"; then 267 | return 0 268 | fi 269 | done 270 | IFS="$originalIFS" 271 | return 1 272 | } 273 | 274 | core_variable_array_iterateShortcut() 275 | { 276 | local variableName="$1" 277 | local callback="$2" 278 | shift 2 279 | 280 | if _core_variable_array_isEmpty; then 281 | return 1 282 | fi 283 | 284 | local core_variable_indirectValue_result 285 | core_variable_indirectValue "$variableName" 286 | 287 | local originalIFS="$IFS" 288 | local IFS="$core_variable_array_delimiter" 289 | local core_variable_array_element 290 | for core_variable_array_element in $core_variable_indirectValue_result 291 | do 292 | IFS="$originalIFS" 293 | 294 | if $callback "$@"; then 295 | return 0 296 | fi 297 | done 298 | IFS="$originalIFS" 299 | return 1 300 | } 301 | 302 | _core_variable_array_contains_check() 303 | { 304 | # return 0 for shortcut 305 | if [ "$core_variable_array_element" = "$containsValue" ]; then 306 | return 0 307 | fi 308 | return 1 309 | } 310 | 311 | core_variable_array_contains() 312 | { 313 | local variableName="$1" 314 | local containsValue="$2" 315 | 316 | if core_variable_array_iterateShortcut "$variableName" _core_variable_array_contains_check; then 317 | return 0 318 | fi 319 | return 1 320 | } 321 | -------------------------------------------------------------------------------- /variable/variable.functions: -------------------------------------------------------------------------------- 1 | # This file is part of shellfire core. It is subject to the licence terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. No part of shellfire core, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file. 2 | # Copyright © 2014-2015 The developers of shellfire core. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/shellfire-dev/core/master/COPYRIGHT. 3 | 4 | 5 | core_init_defines core_variable_isSet 6 | core_init_defines core_variable_isUnset 7 | core_init_defines core_variable_indirectValue 8 | core_init_defines core_variable_unset 9 | 10 | core_variable_setVariable() 11 | { 12 | eval "$1"'=$2' 13 | } 14 | 15 | core_variable_setAndExportVariable() 16 | { 17 | eval export "$1"'=$2' 18 | } 19 | 20 | core_variable_isUnsetOrEmpty() 21 | { 22 | local variableName="$1" 23 | if core_variable_isUnset "$variableName"; then 24 | return 0 25 | fi 26 | 27 | local core_variable_indirectValue_result 28 | core_variable_indirectValue "$variableName" 29 | if [ -z "$core_variable_indirectValue_result" ]; then 30 | return 0 31 | fi 32 | return 1 33 | } 34 | 35 | core_variable_setVariableIfUnset() 36 | { 37 | local variableName="$1" 38 | local variableDefaultValue="$2" 39 | 40 | # This is not whitespace-safe: eval "$variableName=\"\${$variableName-$variableDefaultValue}\"" 41 | if core_variable_isUnset "$variableName"; then 42 | eval "$variableName='$variableDefaultValue'" 43 | fi 44 | } 45 | 46 | core_variable_contains() 47 | { 48 | local value="$1" 49 | local contains="$2" 50 | case "$value" in 51 | 52 | *"$contains"*) 53 | return 0 54 | ;; 55 | 56 | esac 57 | 58 | return 1 59 | } 60 | 61 | core_variable_matches() 62 | { 63 | local value="$1" 64 | local match="$2" 65 | case "$value" in 66 | 67 | $match) 68 | return 0 69 | ;; 70 | 71 | esac 72 | 73 | return 1 74 | } 75 | 76 | #if core_variable_startsWith "/etc/path/to/file" "/home/"; then 77 | # echo 'yes' 78 | #fi 79 | core_variable_startsWith() 80 | { 81 | local value="$1" 82 | local contains="$2" 83 | case "$value" in 84 | 85 | "$contains"*) 86 | return 0 87 | ;; 88 | 89 | esac 90 | 91 | return 1 92 | } 93 | 94 | core_variable_doesNotStartWith() 95 | { 96 | ! core_variable_startsWith "$@" 97 | } 98 | 99 | #if core_variable_endsWith "/etc/path/to/file" "/file"; then 100 | # echo 'yes' 101 | #fi 102 | core_variable_endsWith() 103 | { 104 | local value="$1" 105 | local contains="$2" 106 | case "$value" in 107 | 108 | *"$contains") 109 | return 0 110 | ;; 111 | 112 | esac 113 | 114 | return 1 115 | } 116 | 117 | core_variable_doesNotEndWith() 118 | { 119 | ! core_variable_endsWith "$@" 120 | } 121 | 122 | core_variable_firstCharacter() 123 | { 124 | local value="$1" 125 | local suffix="${value#?}" 126 | printf '%s' "${value%$suffix}" 127 | } 128 | 129 | core_variable_lastCharacter() 130 | { 131 | local value="$1" 132 | local prefix="${value%?}" 133 | printf '%s' "${value#$prefix}" 134 | } 135 | 136 | core_variable_trimSpaceAndHorizontalTab() 137 | { 138 | local value="$1" 139 | 140 | # Remove trailing characters 141 | value="${value#"${value%%[![:blank:]]*}"}" 142 | 143 | # Remove leading characters 144 | printf '%s' "${value%"${value##*[![:blank:]]}"}" 145 | } 146 | 147 | core_variable_trimWhitespace() 148 | { 149 | local value="$1" 150 | 151 | # Remove trailing characters 152 | value="${value#"${value%%[![:space:]]*}"}" 153 | 154 | # Remove leading characters 155 | printf '%s' "${value%"${value##*[![:space:]]}"}" 156 | } 157 | 158 | _core_variable_copy() 159 | { 160 | local valueToCopy="$1" 161 | local copies=$2 162 | 163 | local count=0 164 | while [ $count -lt $copies ] 165 | do 166 | copy="${copy}${valueToCopy}" 167 | count=$((count + 1)) 168 | done 169 | } 170 | 171 | core_variable_allButLastN() 172 | { 173 | local value="$1" 174 | local numberToOmit=$2 175 | 176 | local length=${#value} 177 | local endLength=$((length - numberToOmit)) 178 | if [ $endLength -lt 1 ]; then 179 | return 180 | fi 181 | 182 | local count=0 183 | local match='' 184 | local copy='' 185 | _core_variable_copy '?' $endLength 186 | 187 | local suffix="${value#$copy}" 188 | printf '%s' "${value%$suffix}" 189 | } 190 | 191 | core_variable_allButLast() 192 | { 193 | core_variable_allButLastN "$1" 1 194 | } 195 | 196 | core_variable_allButFirstN() 197 | { 198 | local value="$1" 199 | local numberToOmit=$2 200 | 201 | local length=${#value} 202 | local endLength=$((length - numberToOmit)) 203 | if [ $endLength -lt 1 ]; then 204 | return 205 | fi 206 | 207 | local count=0 208 | local match='' 209 | local copy='' 210 | _core_variable_copy '?' $endLength 211 | 212 | local prefix="${value%$copy}" 213 | printf '%s' "${value#$prefix}" 214 | } 215 | 216 | core_variable_allButFirst() 217 | { 218 | core_variable_allButFirstN "$1" 1 219 | } 220 | 221 | _core_variable_characterByCharacter() 222 | { 223 | local index=0 224 | local core_variable_character 225 | while IFS='' read -r core_variable_character 226 | do 227 | if [ -z "$character" ]; then 228 | character=" 229 | " 230 | fi 231 | $callback 232 | index=$((index+1)) 233 | done 234 | } 235 | 236 | core_variable_characterByCharacter() 237 | { 238 | local value="$1" 239 | local callback="$2" 240 | 241 | local TMP_FILE 242 | core_temporaryFiles_newFileToRemoveOnExit 243 | local inputFile="$TMP_FILE" 244 | prinf '%s' "$value" >"$inputFile" 245 | 246 | core_file_characterByCharacter "$inputFile" _core_variable_characterByCharacter 247 | 248 | rm -f "$inputFile" 249 | } 250 | 251 | core_variable_isTrue() 252 | { 253 | _core_variable_parseBoolean "$1" 0 1 2 254 | } 255 | 256 | core_variable_isFalse() 257 | { 258 | _core_variable_parseBoolean "$1" 1 0 2 259 | } 260 | 261 | core_variable_isInvalidBoolean() 262 | { 263 | _core_variable_parseBoolean "$1" 1 1 0 264 | } 265 | 266 | _core_variable_parseBoolean() 267 | { 268 | case "$1" in 269 | 270 | true|True|TRUE|T|yes|Yes|YES|Y|on|On|ON|1) 271 | return $2 272 | ;; 273 | 274 | false|False|FALSE|F|no|No|NO|N|off|Off|OFF|0) 275 | return $3 276 | ;; 277 | 278 | *) 279 | return $4 280 | ;; 281 | 282 | esac 283 | } 284 | 285 | # eg local my_heredoc_value='$(core_variable_escapeForSingleQuotedLiteralInHeredoc "$my_value")' 286 | core_dependency_requires '*' sed 287 | core_variable_escapeForSingleQuotedLiteralInHeredoc() 288 | { 289 | local value="$1" 290 | 291 | local singleQuote="'" 292 | local doubleQuote='"' 293 | 294 | # '"'"' 295 | local replacement="${singleQuote}${doubleQuote}${singleQuote}${doubleQuote}${singleQuote}" 296 | 297 | # Replaces any embedded ' symbols with '"'"' 298 | printf '%s' "$value" | sed "s/${singleQuote}/${replacement}/g" 299 | } 300 | 301 | core_variable_escapedCommandLine() 302 | { 303 | { 304 | local afterFirst=false 305 | local argument 306 | for argument in "$@" 307 | do 308 | if $afterFirst; then 309 | printf ' ' 310 | else 311 | afterFirst=true 312 | fi 313 | printf "'" 314 | core_variable_escapeSingleQuotes "$argument" 315 | printf "'" 316 | done 317 | printf '\n' 318 | } 319 | } 320 | 321 | core_variable_escapeSingleQuotes() 322 | { 323 | core_variable_escape "$1" "'" "'\''" 324 | } 325 | 326 | core_variable_escape() 327 | { 328 | local value="$1" 329 | local separator="$2" 330 | local replacement="$3" 331 | local result='' 332 | 333 | local split 334 | local remainder="$value" 335 | while [ ${#remainder} -ne 0 ] 336 | do 337 | IFS="$separator" read -r split remainder <<-EOF 338 | ${remainder} 339 | EOF 340 | if [ -n "$result" ]; then 341 | result="${result}${replacement}" 342 | fi 343 | result="${result}${split}" 344 | done 345 | 346 | printf '%s' "$result" 347 | } 348 | --------------------------------------------------------------------------------