when a second config symbol isn't defined. Use this for various LSM -Z
flags, PASSWD_SAD, sort -g, and wget's https support. This replaces the
old help text merging scripts/config2help.c used to do.
The annotation is a leading !, which removes the next char from usage:
lines and the whole line from the rest of the help text. The ! is always
removed, and the data it marks is only shown if the argument to
TOYFLAG_MOREHELP() is true at compile time.
In theory this plumbing should drop out when not used, like lib/args.c.
With `conv=nocreat` set O_CREAT will not be set when
creating the output file, causing an error if of does
not exist.
Test: dd if=/dev/zero of=/tmp/doesnotexist conv=nocreat count=1
Instead of unconditionally logging on the main buffer, allow choosing
the buffer where the log should be sent. The default Android buffers
are supported.
When comparing with files created by GNU tar, I noticed the following
difference:
61 RHT.security.selinux=unconfined_u:object_r:user_tmp_t:s0\x00\n
->
60 RHT.security.selinux=unconfined_u:object_r:user_tmp_t:s0\n
After making toybox tar match GNU one, it no longer complains about bad
header when trying to list the files inside.
Test: tar --selinux -cvf /tmp/a.tar /tmp/a
tar --list -f /tmp/a.tar
When dumping registers with -xxxx, addresses will be larger than 2 hex
digits (256), which means we truncate the column/address. This can
confuse attempts at post-processing this output.
Currently crond uses the modification time of the crontabs directory
to detect changes to the crontab files to decide whether to reload
them. This works fine when crontab creates or removes crontab files,
but when an existing crontab file is modified or replaced, it doesn't
change the modification time of the directory, so crond doesn't know
it should reload the crontab files. This patch fixes this by making
crontab remove the old crontab file (if it exists) before recreating
it, so the directory's modification time always changes when a crontab
is modified.
pgrep currently implements -l and -f, but not -a. It also inadvertently
treats -f as a combination of -a and -f, where we both filter via the
full command line and display the full command line. This violates
--help, where -f says "Check full command line for PATTERN".
Implement -a, which takes care of displaying the full command line, and
return -f to simply checking (filtering) via command line.
pgrep will silently eat unknown args and treat them as process filters.
This is especially confusing for unimplemented options, like "-a".
If one needs to filter on a flag-like filter, there's always a "--"
separator, like:
pgrep -- -process-with-dashes
I found a few more issues I wanted to fix, all related to environment
variables.
- When setting a variable in the crontab file, the value would have a
newline at the end of it. That's because getline() returns the line
with a newline at the end, and the code didn't strip that newline out.
- The HOME variable was being sourced from what HOME was set to when
crond was run, rather than what the user's home is in the passwd file.
I believe the intention was to set HOME to what it is in the passwd
file, but allow the crontab to override it.
- I decided to also set LOGNAME to the username of the crontab's
owner, since the posix manpage for crontab mentions that as one of the
variables that should be set.
It seems the original author of crond slightly messed up the logic for
checking whether the current time matches the time that was specified.
This patch fixes it.
For some reason there was an OR where there should have been an AND,
which meant if the time and day of month OR the month and day of week
match the current time, the job would run. So you'd get jobs running
every minute if the day of week and month match. And if they didn't
match, you'd still get the job running if the time and day of month
match.
Also, in the tm struct, the day of the month (tm_mday) starts at 1,
not the month (tm_mon).
in sh_fcall stack. The main processing loop moved back at the end of
sh_main() doing read/parse/run on TT.ff->source, popping the fcall
stack at EOF and exiting when the stack is empty.
The motivation was "trap" needed to call do_source() from a signal handler
(which it couldn't, even with longjmp) but the result is a noticeably
cleaner design removing several special cases.
Each sh_fcall entry now has a FILE *source which (if not NULL) is where to
read the next line from: "source" is now basically TT.ff->source = fopen(name)
and and "eval" is fmemopen(s, strlen(s), "r"). The starting script and
/etc/profile work like "source", the -c argument works like "eval".
When run_lines() runs out of parsed lines (I.E. TT.ff->pl==NULL),
if TT.ff->source isn't NULL it returns to sh_main(), otherwise it
pops the fcall stack and continues. When sh_main() hits EOF/error on
TT.ff->source it fclose()s it and sets it to NULL so the next call
to run_lines() can pop it and handle trailing cleanup like "eval x && y".
When everything is popped (TT.ff==NULL) the loop exits.
The old design would block until things completed, the new design means
things like "source" add TODO items to the fcall stack which have not
even been started when source_main() returns, so a lot of the
lifetime rules changed, sometimes subtly. For example, the old
do_source(fmemopen("cd .")) style calls in the setup code now run after
the initialization functions return, so the initial value of $_ (the shell
name) was getting overwritten with the "." argument to cd. (It's now
effectively doing "_= cd ." with a prefix assignment to absorb/discard
the update.) The new ff->_ member ("_" is a legal C variable name) solves
a similar problem of $_ updates at the end of "source" and "eval" calls
happening long after source_main() and eval_main() return.
Added reference counting to sh_process, and added sh_process *pp to sh_fcall
to track the TT.ff->arg string lifetimes because free_process() frees them but
when to call that is non-obvious (pp could be backgrounded, etc).
Also removed TT.ff->delete and just have its users always use
TT.ff->pp->delete: the previous code had deletion lists in both places
and the prefix assignment case transplanted pp->delete into ff->delete, which
is one such tangle this redesign smoothed out.
Previously the sh_process's filehandle unredirect list was always processed
at the end of run_command(), but since "command | thingy" and
"function | thingy" do very different things now that doesn't work.
Both need to unredirect() before running "thingy", and most commands finish
before run_command() exits, but source/eval/functions need the redirects to
persist until the fcall context is eventually popped after running the body.
We can't move pp->urd into ff->urd because the redirects are performed
when creating the process (parsing the command line or preparing a pipe
to the next command) before run_command() is called, the relevant fcall
context doesn't exist yet. Answer: have end_fcall() flush and clear urd
for the attached process, if ff->pp isn't NULL end_fcall will
unredirect(ff->pp->urd) of any ff->pp attached to the popped fcall.
(So delete is processed when the last user drops it, but urd is processed
when the FIRST user drops it.)
And run_subshell() sets ff->pp to (void *)1 in the CFG_TOYBOX_FORK child
codepath to signal that end_fcall() should _exit() instead of returning
when this fcall is popped, because a child process running in a subshell
still needs the full fcall stack to resolve layers of local variables,
but should NOT proceeed past the end of its domain to run shell script
that belongs to the parent process. (The previous logic for figuring this
out was one of the most opaque sharp edges in the codebase. There's also
a new TT.forkchild which run_subshell() longjmp()s back to from there,
because the forked child sequencing is unusual at both ends.)
The new design replaces the previous implicit rules to figure out what each
fcall entry meant with much simpler explicit rules. No more "funconly"
argument to end_fcall(): now it always frees one fcall entry (even the last
one, leaving TT.ff null). Each fcall has ->function set if it's a function()
call, ->source set if it's a source of text script lines ("eval" leaves
->name null, "source" sets it), and it's still got the ->var entry with
whiteouts for local variable processing. Calling run_command() creates ONE
fcall entry, which is always there, containing prefix assignments and getting
its source set by source_main() and eval_main(). This means lots of nofork
commands messing with TT.ff got adjusted to look at TT.ff->next instead
because the command's transient function context is not what "break",
"return", "set", or "shift" should be messing with. The old magic "is
ff->var null or not" tests now just check for ff->function.
More cleanup: removed recfile[] (it fclose()s each TT.ff->source instead),
lineno now lives in TT.ff->lineno instead of TT.lineno (no more "oldlineno"
shuffle to match bash behavior), fewer nommu recursion limit checks
(recalculate() still recurses on the C stack but eval eval eval
eval eval eval does not; $(a=$(b=$(c)) forks (subshell) children and waits
for them), parse_line() no longer takes an sh_pipeline argument (just uses
TT.ff->pl) and no longer has a second instance of cleanup code in its
error path (sh_main handles it), get_next_line() no longer returns (void *)1
for "invalid" but just NULL or a string (things like sourcing an ELF binary
now force invalid UTF-8 sequence detection), get_next_line() no longer
takes a special NULL argument meaning "stdin but interactive": when the
first argument is NULL it returns NULL (meaning EOF/error) immediately,
nommu_entry() and subshell_setup() behave similarly: both return instead
of one blocking and the other returning, each cues up the appropriate
input source(s) in the TT.ff stack, and the setup logic has mostly moved
into the setup functions instead of being at the start of sh_main().
Deleting do_source() removed the need for a function prototype (alas
free_pipeline()/free_function() and setvar()/recalculate() can still loop),
New sherror_msg() function to display source/function and lineno,
replacing calls to perror_msg() and being called by syntax_err().
Switch perror_msg() to sherror_msg() to display source/function and lineno.
Cleaned up setvar_found()'s handling of the freeable argument,
call_function() now returns the new TT.ff so we can just -> tweak it
right after the call.
We're seeing ever more zstd-compressed files in the wild, so even though
toybox can't compress/decompress zstd without an external helper, it
still seems useful to integrate with any that happens to be on the
system.
Setting NF=0 didn't work and setting it negative failed to abort. Setting NF=0 now sets $0 to an empty string. Also fixed call to wrong err msg func in run.c