summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* test-functions: do not check that genfun_time is greater than -1Kerin Millar2024-08-171-1/+1
| | | | | | | | In point of fact, it can be expected to overflow sometimes. Especially if running mksh. Fixes: 52f551e5a01ab030c131c2e7f196a8a76235583d Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Render the non-bash srandom() implementation fasterKerin Millar2024-08-111-1/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Presently, there are three implementations of srandom(), one of which is the preferred implementation for shells other than bash. It is a little on the slow side as it has to fork and execute both od(1) and tr(1) every time, just to read 4 bytes. Accelerate it by having the shell maintain its own entropy pool of up to 512 hex digits in size. Consider the following benchmark. i=0; while [ $((i += 1)) -le 30000 ]; do srandom; done >/dev/null As conducted with dash on a system with a 2nd generation Intel Xeon, I obtained the following figures. BEFORE real 0m49.878s use 1m1.985s sys 0m17.035s AFTER real 0m12.866s user 0m12.559s sys 0m0.962s It should be noted that the optimised routine will only be utilised in cases where the kernel is Linux and the shell has not forked itself. $ uname Linux $ srandom # uses the fast path $ number=$(srandom) # subshell; probably uses the slow path $ srandom | { read -r number; } # ditto Still, there are conceivable use cases for which this optimisation may prove useful. Below is an example in which it is known in advance that up to 100 random numbers are required, and where writing them to temporary storage is not considered to be a risk. i=0 tmpfile=${TMPDIR:-/tmp}/random-numbers.$$.$(srandom) while [ $((i += 1)) -le 100 ]; do srandom done > "$tmpfile" while read -r number; do do_something_with "$number" done < "$tmpfile" Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: consistently align the test parameter declarationsKerin Millar2024-08-111-132/+132
| | | | | | | This is merely a whitespace cleanup. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: don't increment testnum by 2 for test_ebegin()Kerin Millar2024-08-111-8/+10
| | | | | | | | Also, restore the correct test_description string, which was being lost in a subshell. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: comment as to why test_quote_args() fails for yashKerin Millar2024-08-111-0/+6
| | | | | Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: comment as to the implications of test_local() failingKerin Millar2024-08-111-0/+8
| | | | | | | | In particular, comment as to why the test can be expected to fail for ksh93 and - in some cases - yash. Signed-off-by: Kerin Millar <kfm@plushava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: account for the potential absence of test(1) as a builtinKerin Millar2024-08-111-5/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Presently, the test_whenceforth() function potects itself from being adversely affected by printf(1) not being a builtin utility. Consider the following test. PATH=. whenceforth -x newer/file Owing to the modification of PATH, it becomes impossible to execute any of the standard utilities unless they happen to be builtins. The workaround is to temporarily define printf as a function which duly executes the external utility. Having run the test suite with the yash shell, it has served as a sharp reminder that one cannot assume that test(1) is always available as a builtin either. In fact, yash implements test(1) as a "substitutative built-in command". Below is the relevant material from its manual. - https://magicant.github.io/yash/doc/builtin.html#types - https://magicant.github.io/yash/doc/exec.html#search - https://magicant.github.io/yash/doc/index.html#builtins It is a curious thing, to say the least. Essentially, substitutative builtins can only be used for as long as an executable of the same name can be found in PATH. Since the purpose of test_whenceforth() is not to directly evaluate the behaviour of the test(1) utility, this commit implements the same safeguard for test(1) as is present for printf(1). Signed-off-by: Kerin Millar <kfm@plushava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Render _update_time() a no-op for the yash shellKerin Millar2024-08-111-0/+12
| | | | | | | | | | | | | | | | | | When integer overflow occurs in a non-interactive yash shell, it prints "yash: arithmetic: overflow" as a diagnostic message before proceeding to exit. That makes it extremely difficult for the arithmetic in the _should_throttle() function to be implemented safely for it. For now, ensure that _update_time() does nothing for yash but return a non-zero status code. In turn, this disables the rate limiting feature for yash. Additionally, refrain from running test_update_time() and test_should_throttle() for yash in test-functions. The former would only amount to a waste of time and the latter would be guaranteed to fail. For the record, my testing was performed with yash 2.56.1. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Handle integer overflow as a special case in _should_throttle()Kerin Millar2024-08-111-0/+47
| | | | | | | | | | | | | | | | At the point that the genfun_time variable overflows, guarantee that the should_throttle() function behaves as if no throttling should occur rather than proceed to perform arithmetic based on the result of deducting genfun_last_time from genfun_time. Further, guarantee that the should_throttle() function behaves as if no throttling should occur upon the very first occasion that it is called, provided that the call to update_time() succeeds. Finally, add a test case. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: choose a better variable name for storing the temp dirKerin Millar2024-08-111-5/+5
| | | | | | | | | | | The name, dir, is rather generic. Rename it to global_tmpdir to diminish the likelihood of an accidental name space conflict. Also, don't pass the -f option to rm(1) at the point that the directory is to be removed. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: silence several shellcheck false-positivesKerin Millar2024-08-111-1/+3
| | | | | Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: declare local variables where possibleKerin Millar2024-08-111-2/+31
| | | | | | | | | Given that test-functions bails out immediately in the absence of a conventional local builtin, one might as well. Besides, it would be trivial to eliminate local in the future, if so desired. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: have three tests employ callback functionsKerin Millar2024-08-111-51/+48
| | | | | | | | | Convert test_local(), test_ebegin() and test_quote_args() so as to declare and use callbacks, just like the other tests. An appreciable code cleanup is the result. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Avoid unspecified behaviour around simple commands in generalKerin Millar2024-08-111-19/+24
| | | | | | | | | | | | | | | | | | | | | | As mentioned by the previous commit, the Shell Command Language leaves it unspecified as to whether variable assignments affecting the execution environment of a simple command charged with executing a function (that is not the implementation of a standard utility) shall persist after the completion of the function. It transpires that modifying gentoo-functions so as to steer clear of this pitfall isn't particularly difficult so this commit does exactly that. Most of the changes are in test-functions but functions/rc.sh also required some minor changes regarding the use of the GENFUN_CALLER variable. With this, loksh very nearly passes the test suite. There is one individual test that continues to fail, although it looks as though that may be caused by a genuine bug on the part of the shell. That will require investigating in its own right. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: test for simple commands persisting environmental changesKerin Millar2024-08-111-1/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some implementations allow for alterations made to the execution environment to persist beyond the scope of a simple command. Consider loksh as a case in point. $ f() { :; } $ unset LEAKED $ LEAKED=1 /bin/true; echo "LEAKED = $LEAKED" LEAKED = $ LEAKED=1 cmd2; echo "LEAKED = $LEAKED" LEAKED = 1 Strictly speaking, such behaviour is permitted. The Shell Command Language specification states: """ If the command name is a function that is not a standard utility implemented as a function, variable assignments shall affect the current execution environment during the execution of the function. It is unspecified: - Whether or not the variable assignments persist after the completion of the function - Whether or not the variables gain the export attribute during the execution of the function - Whether or not export attributes gained as a result of the variable assignments persist after the completion of the function (if variable assignments persist after the completion of the function) """ Unfortunately, loksh elects not to be aligned with the practices of the overwhelming majority of implementations in this regard. For now, have test-functions detect and abort for shells that go against the grain. I shall consider reviewing and adapting gentoo-functions to account for such unspecified behaviour but it is not an immediate priority. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: avoid unspecified behaviour in test_quote_args()Kerin Millar2024-08-111-1/+1
| | | | | | | | | | | | | | | | | In test_quote_args(), there is the following code. fmt=$(printf '\%o' "$i") However, the behaviour of the <backslash> character followed by the <number-sign> character is unspecified. Since it is intended to be taken as a literal backslash, fix it by writing it as thus. fmt=$(printf '\\%o' "$i") Doing so addresses a spurious test failure where using the loksh shell. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Have srandom() employ an upper bound of 2^31-1Kerin Millar2024-08-111-4/+8
| | | | | | | | | | | | | | | | | | In the case of some shells - mksh, at least - the maximum value of an integer is 2147483647. Such is a consequence of implementing integers as signed int rather than signed long, even though doing so contravenes the specification. Reduce the output range of srandom() so as to be between 0 and 2147483647, rather than 0 and 4294967295. A change of this scope would normally justify incrementing GENFUN_API_LEVEL but I shall not do so on this occasion. My rationale is that >=gentoo-functions-1.7 has not yet had enough exposure for srandom() to be in use by other projects. Additionally, have test-functions test srandom() 10 times instead of 5. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: check numerical bounds with awk in test_srandom()Kerin Millar2024-08-111-2/+1
| | | | | | | | | | | | | Use awk(1) to test whether the numbers produced by the srandom() function are within bounds. One cannot necesarily rely upon the shell to perform this task. Consider mksh(1) as a case in point. Contrary to the specification, it implements integers as signed int rather than signed long. Consequently, it can only handle numbers between -2147483648 and 2147483647, resulting in easily reproducible test failures caused by overflow. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Avoid a subshell for is_identifier()Kerin Millar2024-08-111-1/+9
| | | | | | | Also, extend the coverage of the test suite a little further. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: refactor the newest() test caseKerin Millar2024-08-111-17/+29
| | | | | | | | | | | | Rework the test case for the newest() function in accordance with the recently added test case for the oldest() function. The resulting code is more pleasant to read and maintain. In doing so, an obscure bug has been addressed. Hitherto, an empty NUL-terminated record had erroneously being conveyed to newest() for just one of the 28 individual sub-tests being conducted. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: test the oldest() functionKerin Millar2024-08-111-0/+67
| | | | | | | Test the oldest() function in addition to the newest() function. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Make _select_by_mtime() work correctly for paths read from STDINKerin Millar2024-08-111-2/+18
| | | | | | | | | | | | | | | The _select_by_mtime() function is called by both newest() and oldest(). Pathnames may be specified as positional parameters or as NUL-separated records to be read from the standard input. Unfortunately, the latter interface does not work at all. Rectify this by checking whether the number of parameters is greater then 0, rather than greater than or equal to 0. Also, extend the existing test case in such a way that the interface in question is tested. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test_functions: check that genfun_time is greater than -1Kerin Millar2024-08-111-1/+1
| | | | | | | | After all, it is never expected to be negative. Signed-off_by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* test-functions: try to test a locale whose radix character isn't U+2EKerin Millar2024-08-111-17/+40
| | | | | Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Ensure a radix character of U+2E in _update_time()Kerin Millar2024-08-051-0/+22
| | | | | | | | | | | | | | | | | | | | I overlooked that bash respects the radix character defined by the locale in the course of synthesizing the value of the EPOCHREALTIME value. Set LC_NUMERIC as C to guarantee that the radix character is considered as U+2E (FULL STOP) within the scope of the bash-specific function. Doing so also addresses a distinct issue whereby the invocation of printf was sensitive to the implied value of LC_NUMERIC. Another way to address this would have been to set LC_ALL as C. I decided not to because it would decrease the likelihood of the relevant diagnostic messages being rendered in the user's native language. Additionally, add a test case. Closes: https://bugs.gentoo.org/937376 Reported-by: Christian Bricart <christian@bricart.de> Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
* Add the assign() and deref() functionsKerin Millar2024-08-051-0/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | These two functions are primarily intended to mitigate the appalling use of eval in projects such as netifrc and openrc. Consider the following code. net/iproute2.sh:29: eval netns="\$netns_${IFVAR}" This could instead be be written as: deref "netns_${IFVAR}" netns Alternatively, it could be written so as to use a command substitution: netns=$(deref "netns_${IFVAR}") Either method would protect against against illegal identifier names and code injection. Consider, also, the following code. net/iproute2.sh:185: eval "$x=$1" ; shift ;; This could instead be written as: assign "$x" "$1" As with deref, it would protect against illegal identifier names and code injection. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* test-functions: add several shellcheck exemptionsKerin Millar2024-08-031-1/+3
| | | | | | | Notably, SC2317 and SC3034 in the global scope. The former produces false positives whereas the latter permits the use of local. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* test-functions: jettison a few shellcheck exemptionsKerin Millar2024-08-031-2/+1
| | | | | | They are no longer applicable. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Have chdir() enforce POSIX interpretation 1047Kerin Millar2024-08-031-16/+1
| | | | | | | | | | | | POSIX-1.2024 (Issue 8) requires for the cd builtin to raise an error where given an empty directory operand. However, various implementations have yet to catch up. Given that it is a sensible change, let's have the chdir() function behave accordingly. Further, since doing so renders the test_chdir_noop test useless, get rid of it. The purpose that the test served is now subsumed by test_chdir. Closes: https://bugs.gentoo.org/937157 Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Have hr() employ a divide-by-16 strategyKerin Millar2024-08-021-2/+2
| | | | | | | | | | | | | | | A factor of 16 was shown to be faster on average by timing how long it takes for bash to print a rule 5000 times for all lengths between 40 and 132, inclusive. Factor Time StdDev 8 87.004000 3.961607 16 82.893000 3.971257 Further, 16 remains a factor of 80, which is often the number of columns that a terminal emulator is initialised with. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Move is_subset() to experimentalKerin Millar2024-08-021-1/+1
| | | | | | | I'm not yet ready to commit to it being among the core functions for the inaugural API level. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Render hr() faster still for shells other than bashKerin Millar2024-08-021-2/+2
| | | | | | | Reduce the number of loop iterations by initially trying to append characters 8 at a time. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Render hr() fasterKerin Millar2024-08-021-1/+1
| | | | | | | | | | Render hr() faster by eliminating the requirement to fork and execute any external utilities after having established the intended length of the rule. Also, use printf -v and string-replacing parameter expansion where the shell is found to be bash. Doing so helps considerably because bash is very slow at looping. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Render contains_all() and contains_any() fasterKerin Millar2024-08-021-94/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Re-implement the contains_all() and contains_any() functions in such a way that they are faster than their forebears by an order of magnitude. In order to achieve this level of performance, the value of IFS is no longer taken into account. Instead, words are always presumed to be separated by characters matching the [[:space:]] character class. Consider a scenario in which the FEATURES variable is comprised of 33 words. $ FEATURES="assume-digests binpkg-docompress binpkg-dostrip binpkg-logs buildpkg buildpkg-live config-protect-if-modified distlocks ebuild-locks fixlafiles ipc-sandbox merge-sync merge-wait multilib-strict network-sandbox news parallel-fetch pid-sandbox pkgdir-index-trusted preserve-libs protect-owned qa-unresolved-soname-deps sandbox sfperms strict unknown-features-warn unmerge-logs unmerge-orphans userfetch userpriv usersandbox usersync xattr" Let's say that the contains_any function is used to search for 10 words, where only the 10th can be matched and where FEATURES must be scanned in its entirety exactly 10 times. $ contains_any "$FEATURES" the quick brown fox jumped over the lazy hen xattr The following benchmarks show how long it took to call the function 50,000 times consecutively on a system with an Apple M1 CPU for both the original and new implementations. This is with the dash shell. contains_any (BEFORE) real 0m19.135s user 0m16.781s sys 0m2.258s contains_any (AFTER) real 0m1.571s user 0m1.497s sys 0m0.063s Now let's say that the contains_all function is used to search for 3 words, where all can be matched while requiring for FEATURES to be scanned in its entirety at least once. $ contains_all "$FEATURES" assume-digests news xattr Again, The following benchmarks show how long it took to call the function 50,000 times consecutively. contains_all (BEFORE) real 1m8.052s user 0m19.363s sys 0m42.742s contains_all (AFTER) real 0m0.689s user 0m0.627s sys 0m0.057s The performance improvements are similarly impressive if using bash. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Render quote_args() robust and implement a test caseKerin Millar2024-08-021-0/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Coerce the effective character set as being C (US-ASCII) in the course of executing awk(1). Some implementations are strict and will otherwise fail in situations where the bytes cannot be decoded. $ uname -o Darwin $ echo "$LC_ALL" en_GB.UTF-8 $ printf '\200' | awk '/[\001-\037\177-\377]/' awk: towc: multibyte conversion failure on: '' In the above case, awk aborts because it has a need to decode the input, which turns out not to be valid UTF-8. Now, it is rather beyond the purview of quote_args() to guarantee that its parameters adhere to any particular character encoding. Fortunately, for it to contend with strings on a byte-by-byte basis is acceptable. Refactor the code somewhat. The behaviour has been adjusted so to be virtually identical to that of the "${*@Q}" expansion in bash, with the exception that the ESC character is rendered as $'\e' instead of $'\E'. Such an exception is necessary for POSIX-1.2024 conformance, wherein dollar-single-quotes are now a standard feature (see section 2.2.4 of the Shell Command Language). Revise the comment preceding the function so as to accurately document its behaviour. Finally, add a test case. It works by calling quote_args for every possible single-byte string before calculating a CRC checksum for the cumulative output and comparing it against a pre-determined value. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* test-functions: Check whether local is supportedKerin Millar2024-07-101-29/+53
| | | | | | | | | Test whether the (non-standard) local builtin is present and behaving in a manner considered to be conventional. Should the test fail, refrain from conducting any further tests. This causes the test suite to fail early for ksh - a shell not currently supported by the project. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Correct the implementation of contains_all()Kerin Millar2024-07-081-32/+94
| | | | | | | It was not translating IFS to FS correctly. Have it do so and extend the test suite accordingly. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the contains_all() and contains_any() functionsKerin Millar2024-07-011-0/+80
| | | | | | | | | | | | | | | | | | Here are some examples which presume the default value of IFS. contains_all " cat mat " cat dog # returns 1 contains_all " cat mat " mat cat # returns 0 contains_any " cat mat " cat dog # returns 0 contains_any " cat mat " dog # returns 1 Here are some examples showing that IFS is taken into account. IFS=, contains_all "cat,mat" cat dog # returns 1 IFS=, contains_all "cat,mat" mat cat # returns 0 IFS=, contains_any "cat,mat" cat dog # returns 0 IFS=, contains_any "cat,mat" dog # returns 1 Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Move substr() to experimentalKerin Millar2024-07-011-1/+1
| | | | | | | Though it works very well, I'm not yet ready to commit to it being among the core functions for the inaugural API level. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Have whenceforce() require the -x option to check the execute bitKerin Millar2024-06-281-20/+37
| | | | | | | | This renders the behaviour of whenceforth() almost equivalent to type -P in the absence of the -x option, the exception being that whenceforth() never consults the hash table. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the substr() functionKerin Millar2024-06-281-0/+39
| | | | | | | POSIX sh does not support substring expansion so it may come in handy. The implementation is based on the awk function of the same name. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the trueof_all() and trueof_any() functionsKerin Millar2024-06-251-0/+44
| | | | | | | | | | | | | | These functions allow for it to be determined whether an arbitrary simple command yields true for either all of an arbitrary list of parameters or at least one of them. The simple command shall be given each parameter, one at a time. Some examples are shown below. trueof_all test -d -- / /var/empty # returns 0 trueof_all test -d -- / /dev/null # returns 1 trueof_any test -d -- / /dev/null # returns 0 trueof_any test -d -- /etc/fstab /dev/null # returns 1 Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Render gentoo-functions modular in natureKerin Millar2024-06-231-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For many years, the implied purpose of gentoo-functions has been to provided parallel implementations of utilities provided by OpenRC, along with a handful of peripheral functions. It is probably also fair to say that it has not seen much in the way of maintenance until comparatively recently. As of the present day, the status quo is not ideal. For one thing, the library has never been particularly useful beyond this definition. It is my hope that some of the recently added functions will be well received by those needing to write effective shell scripts in Gentoo for a number of relevant tasks. Certainly, there remains ample room for improvement in that regard. For another thing, the implementation of gentoo-functions is presently inflexible. For instance, it is impossible to source the functions from an OpenRC runscript without overriding the OpenRC implementations. Nor may one source the functions from an ebuild or eclass without overriding the Portage implementations. Indeed, it is has become something of a mess. Not only does gentoo-functions implement a number of functions that shadow the OpenRC implementations but so does Portage, owing to the existence of its "isolated-functions.sh" unit. What's more, the various implementations are of varying quality and do not necessarily behave in the same manner. This commit aims to address some of these issues by rendering gentoo-functions modular in nature. It establishes the premise of having a core library, with collections of additional functions being optionally declarable. As such, all of the functions that shadow OpenRC have been relocated to a unit named "rc.sh". This first change encompasses the following public functions: - ebegin - eend - eerrorn - eindent - einfon - eoutdent - esyslog - ewarnn - ewend - get_bootparam - is_older_than - veend - vewend - yesno Similarly, all of the functions that exclusively shadow Portage have been relocated to a unit named "portage.sh". This second change encompasses the following public functions: - die - edo - eqatag - eqawarn The functions that remain in the "functions.sh" unit may now be considered as core functions. To accommodate all of this, a new GENFUN_MODULES variable is supported, whose behaviour is described herewith. If GENFUN_MODULES is found to be set at the time of "functions.sh" being sourced, it shall be taken as a list of zero or more blank-separated words. In turn, these words shall be taken as the basenames of potentially available modules - not including the .sh suffix. Presently, the only supported module names are "rc" and "portage". Should either or both of these names be present, their respective units shall be automatically sourced. If neither are present, no additional units shall be sourced. Consequently, it becomes possible for a consumer of gentoo-functions to request that only the core functions be declared by writing: GENFUN_MODULES= . /lib/gentoo/functions.sh If, on the other hand, GENFUN_MODULES is found not to be set then heuristics shall be employed to determine which of the additional units should be sourced. The intent of these heuristics is twofold. Firstly, to maintain an adequate degree of backward-compatibility and, secondly, to act as is appropriate based on the characteristics of the operating environment. The exact behaviour of these heuristics is as follows. If the present shell is neither executing a runscript nor a subprocess of one, the ensuing behaviour shall be as if "rc" had initially been among the names defined by the GENFUN_MODULES variable. If the present shell is not a subprocess of portage, the ensuing behaviour shall be as if "portage" had initially been among the names defined by the GENFUN_MODULES variable. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the is_anyof() and is_subset() functionsKerin Millar2024-06-141-0/+49
| | | | | | | | | | | | Examples follow. is_anyof y x y z # returns 0 is_anoyf y x w z # returns 1 is_subset x y -- x y z # returns 0 is_subset x y z -- z y x # returns 0 is_subset x y -- x w z # returns 1 Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Promote _print_args() to the public function, quote_args()Kerin Millar2024-06-121-14/+14
| | | | Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the parallel_run() functionKerin Millar2024-06-121-1/+20
| | | | | | | | | | | | | | Here is an example of how to use it. $ parallel_run 0 sha256sum dir/* Simple commands of a greater level of sophistication can easily be composed with the aid of functions. $ sm3sum() { cksum -a sm3 "$@"; } $ parallel_run 0 sm3sum dir/* Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the get_nprocs() functionKerin Millar2024-06-121-0/+12
| | | | | | | It stands a good chance of printing a useful value, even in the case that nproc(1) from coreutils is unavailable. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the whenceforth() function as a type -P alternativeKerin Millar2024-06-121-0/+39
| | | | | | | It acts much as type -P does in bash. I would have liked to name it whence but ksh and zsh already have builtins by that name. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the hr() function to print a horizontal ruleKerin Millar2024-06-121-0/+24
| | | | | | As based on the implementation in Maarten Billemont's bashlib library. Signed-off-by: Kerin Millar <kfm@plushkava.net>
* Add the trim() functionKerin Millar2024-06-121-0/+29
| | | | | | As based on the implementation in Maarten Billemont's bashlib library. Signed-off-by: Kerin Millar <kfm@plushkava.net>