scripts the way sysctl(8) is. The -N option, like in sysctl(8),
displays only the kenv names, not their values. The -v option prints an
individual kenv variable name with its value as name="value". This is
the inverse of sysctl(8)'s -n flag, since the default behaviour of
kenv(1) is already like sysctl(8) -n.
Submitted by: Garrett Cooper < yanegomi AT gmail DOT com >
MFC after: 1 week
quotation. Also make sure we have the same amount of columns in each row as
the number of columns we specify in the head arguments.
Reviewed by: brueffer
This uses vfork() for simple commands and command substitutions containing a
single simple command, invoking an external program under certain conditions
(no redirections or variable assignments, non-interactive shell, no job
control). These restrictions limit the amount of code executed in a vforked
child.
There is a large speedup (for example 35%) in microbenchmarks. The
difference in buildkernel is smaller (for example 0.5%) but still
statistically significant. See
http://lists.freebsd.org/pipermail/freebsd-hackers/2012-January/037581.html
for some numbers.
The use of vfork() can be disabled by setting a variable named
SH_DISABLE_VFORK.
In the first command of a 'for', $? should be the exit status of the last
pipeline (command substitution in the word list or command before 'for'),
not always 0.
Before this fix, only the first statement of the trap was executed if
evalskip was set. This is for example the case when:
o "-e" is set for this shell
o a trap is set on EXIT
o a function returns 1 and causes the script to abort
Reviewed by: jilles
MFC after: 2 weeks
Also, rework evalcase() to not evaluate any tree. Instead, return the
NCLISTFALLTHRU node and handle it in evaltree().
Fixed bugs:
* If a ;& list with non-zero exit status is followed by an empty ;; or final
list, the exit status of the case command should be equal to the exit
status of the ;& list, not 0.
* An empty ;& case should not reset $?.
* If no pattern is matched, POSIX says the exit status shall be 0 (even if
there are command substitutions).
* If a pattern is matched and there are no command substitutions, the first
command should see the $? from before the case command, not always 0.
The errno message display added in r222292 did not take attempting to
cd to a non-directory or something that cannot be stat()ed into account.
PR: bin/164070
MFC after: 10 days
This improves performance for globs where a slash or another component
follows a component with metacharacters by eliminating unnecessary attempts
to open directories that are not.
This is not necessary: errors are already caught in evalbackcmd() and
forcelocal handles changes to variables.
Note that this depends on r223024.
MFC after: 4 weeks
Free expanded case text before executing commands.
Remove impossible evalskip checks (expanding an argument cannot set
evalskip anymore since $(break) and the like are properly executed in a
subshell environment).
For these simple utilities, it doesn't harm to make all global variables
static. In fact, this allows the compiler to perform better forms of
optimisation and analysis.
display() to calculate column widths, but was not initialized in
main(). This resulted in a division by zero.
Noticed by: Michael Butler <imb@protected-networks.net>
- In the argc == 0 case, just populate the mount list as before, but
do not calculate widths, update totals or print anything.
- In the argv > 0 case, collect information about the requested file
systems and store it in the mount list, but do not calculate
widths, update totals or print anything.
- In either case, once all the information has been collected,
iterate once through the mount list to calculate widths and totals,
then once more to print everything.
This also fixes two bugs: firstly, column widths were not calculated
correctly if more than one file system was specified on the command
line; and secondly, file systems with MNT_IGNORE were included in the
totals even if -a was not specified.
Noticed by: Paul Schenkeveld
MFC after: 3 weeks
- there's no reason the semantics of the -x flag are being explained in
the -a flag description
- be more precise regarding the relation between the -a flag and the
security.bsd.see_other_uids sysctl
- describe the format of the -t flag's argument
- 'con' no longer is a possible entry in the 'TT' column
- explain that the 'TT' column refers to pseudo-terminals via mere numbers
- add a hint in the 'tt' keyword description that a keyword 'tty' exists,
which will give the full terminal pathname
Submitted by: arundel (via docs@) (original)
MFC after: 1 week
With-MFC: 225908
As of FreeBSD 6, devices can only be opened through devfs. These device
nodes don't have major and minor numbers anymore. The st_rdev field in
struct stat is simply based a copy of st_ino.
Simply display device numbers as hexadecimal, using "%#jx". This is
allowed by POSIX, since it explicitly states things like the following
(example taken from ls(1)):
"If the file is a character special or block special file, the
size of the file may be replaced with implementation-defined
information associated with the device in question."
This makes the output of these commands more compact. For example, ls(1)
now uses approximately four columns less. While there, simplify the
column length calculation from ls(1) by calling snprintf() with a NULL
buffer.
Don't be afraid; if needed one can still obtain individual major/minor
numbers using stat(1).
Because sh executes commands in subshell environments without forking in
more and more cases (particularly from 8.0 on), it makes sense to describe
subshell environments more precisely using ideas from POSIX, together with
some FreeBSD-specific items.
In particular, the hash and times builtins may not behave as if their state
is copied for a subshell environment while leaving the parent shell
environment unchanged.
to re-establishment of 64bit arithmetic, but is committed separately, to
not obscure that conversion. This commit does not change the observed
behaviour of expr in any way. Style will be fixed in a follow-up commit.
again. This brings back the behaviour of expr in FreeBSD-4, which had been
reverted due to an assumed incompatbility with POSIX.1 for FreeBSD-5.
This issue has been discussed in the freebsd-standards list, and the
consensus was, that POSIX.1 is in fact not violated by this extension,
since it affects only cases of POSIX undefined behaviour (overflow of
signed long).
Other operating systems did upgrade their versions of expr to support
64bit range, after it had been initially brought to FreeBSD. They have
used it for a decade without problems, meanwhile.
The -e option is retained, but it will only select less strict checking
of numeric parameters (leading white-space, leading "+" are allowed and
skipped, an empty string is considered to represent 0 in numeric context.)
The call of check_utility_compat() as a means of establishing backwards
compatibility with FreeBSD-4 is considered obsolete, but preserved in
this commit. It is expected to be removed in a later revision of this
file.
Reviewed by: bde, das, jilles
MFC after: 2 month (those parts that do not violate POLA)
* Shell patterns are also for ${var#pat} and the like.
* An '!' by itself will not trigger pathname generation so do not call it a
meta-character, even though it has a special meaning directly after an
'['.
* Character ranges are locale-dependent.
* A '^' will complement a character class like '!' but is non-standard.
MFC after: 1 week
POSIX requires a -h option to sh and set, to locate and remember utilities
invoked by functions as they are defined. Given that this
locate-and-remember process is optional elsewhere, it seems safe enough to
make this option do nothing.
POSIX does not specify a long name for this option. Follow ksh in calling it
"trackall".
Replacing ;; with the new control operator ;& will cause the next list to be
executed as well without checking its pattern, continuing until a list ends
with ;; or until the end of the case statement. This is like omitting
"break" in a C "switch" statement.
The sequence ;& was formerly invalid.
This feature is proposed for the next POSIX issue in Austin Group issue
#449.
The eval special builtin now runs the code with EV_EXIT if it was run
with EV_EXIT itself.
In particular, this eliminates one fork when a command substitution contains
an eval command that ends with an external program or a subshell.
This is similar to what r220978 did for functions.
Have mkbuiltins write the prototypes for the *cmd functions to builtins.h
instead of builtins.c and include builtins.h in more .c files instead of
duplicating prototypes for *cmd functions in other headers.
In optimized command substitution, save and restore any variables changed by
expansions (${var=value} and $((var=assigned))), instead of trying to
determine if an expansion may cause such changes.
If $! is referenced in optimized command substitution, do not cause jobs to
be remembered longer.
This fixes $(jobs $!) again, simplifies the man page and shortens the code.
When I added UTF-8 support in r221646, the LC_COLLATE-based ordering broke
because of sign extension of char.
Because of libc restrictions, this does not work for UTF-8. For UTF-8
locales, ranges always use character code order.
In most cases, login shells are started from the home directory, but not in
all, such as xterm -ls.
This commit depends on r222957 for read_profile() performing parameter
expansion.
PR: bin/50569
The function name expandstr() and the general idea of doing this kind of
expansion by treating the text as a here document without end marker is from
dash.
All variants of parameter expansion and arithmetic expansion also work (the
latter is not required by POSIX but it does not take extra code and many
other shells also allow it).
Command substitution is prevented because I think it causes too much code to
be re-entered (for example creating an unbounded recursion of trace lines).
Unfortunately, our LINENO is somewhat crude, otherwise PS4='$LINENO+ ' would
be quite useful.
The "exp" builtin is undocumented, non-standard and not very useful.
If exp's return value is not used, something like
VAR=$(exp EXPRESSION)
is equivalent to
VAR=$((EXPRESSION))
except that errors in the expression are fatal and quoting special
characters is not needed in the latter case.
If exp's return value is used, something like
if exp EXPRESSION >/dev/null
can be replaced by
if [ $((EXPRESSION)) -ne 0 ]
with similar differences.
The exp-run showed that "let" is close enough to bash's and ksh's builtin
that removing it would break a few ports. Therefore, "let" remains in 9.x.
PR: bin/104432
Exp-run done by: pav (with some other sh(1) changes)
CDPATH should be ignored not only for pathnames starting with '/' but also
for pathnames whose first component is '.' or '..'.
The man page already describes this behaviour.
If IFS is null, unquoted $@/$* should still expand to separate words.
This differs from quoted $@ (which does not depend on IFS) in that pathname
generation is performed and empty words are removed.
If the length of a directory in PATH together with the given filename
exceeded FILENAME_MAX (which may happen even for pathnames that work), a
static buffer was overflown.
The static buffer is unnecessary, we can use the stalloc() stack.
Obtained from: NetBSD
MFC after: 1 week
This reflects failure to determine the pathname of the new directory in the
exit status (1). Normally, cd returns successfully if it did chdir() and the
call was successful.
In POSIX, -e only has meaning with -P; because our -L is not entirely
compliant and may fall back to -P mode, -e has some effect with -L as well.
This is sometimes used with eval or old-style command substitution, and most
shells other than ash derivatives allow it.
It can also be used with scripts that violate POSIX's requirement on the
application that they end in a newline (scripts must be text files except
that line length is unlimited).
Example:
v=`cat <<EOF
foo
EOF`
echo $v
This commit does not add support for the similar construct with new-style
command substitution, like
v=$(cat <<EOF
foo
EOF)
This continues to require a newline after the terminator.
Because we have no iconv in base, support for other charsets is not
possible.
Note that \u/\U are processed using the locale that was active when the
shell started. This is necessary to avoid behaviour that depends on the
parse/execute split (for example when placing braces around an entire
script). Therefore, UTF-8 encoding is implemented manually.
?, [...] patterns match codepoints instead of bytes. They do not match
invalid sequences. [...] patterns must not contain invalid sequences
otherwise they will not match anything. This is so that ${var#?} removes the
first codepoint, not the first byte, without putting UTF-8 knowledge into
the ${var#pattern} code. However, * continues to match any string and an
invalid sequence matches an identical invalid sequence. (This differs from
fnmatch(3).)
This ensures that mbrtowc(3) can be used directly once it has been verified
that there is no CTL* byte. Dealing with a CTLESC byte within a multibyte
character would be complicated.
The new values do occur in iso-8859-* encodings. This decreases efficiency
slightly but should not affect correctness.
Caveat: Updating across this change and rebuilding without cleaning may
yield a subtly broken sh binary. By default, make buildworld will clean and
avoid problems.
A string between $' and ' may contain backslash escape sequences similar to
the ones in a C string constant (except that a single-quote must be escaped
and a double-quote need not be). Details are in the sh(1) man page.
This construct is useful to include unprintable characters, tabs and
newlines in strings; while this can be done with a command substitution
containing a printf command, that needs ugly workarounds if the result is to
end with a newline as command substitution removes all trailing newlines.
The construct may also be useful in future to describe unprintable
characters without needing to write those characters themselves in 'set -x',
'export -p' and the like.
The implementation attempts to comply to the proposal for the next issue of
the POSIX specification. Because this construct is not in POSIX.1-2008,
using it in scripts intended to be portable is unwise.
Matching the minimal locale support in the rest of sh, the \u and \U
sequences are currently not useful.
Exp-run done by: pav (with some other sh(1) changes)
Note that this only applies to variables that are actually used.
Things like (0 && unsetvar) do not cause an error.
Exp-run done by: pav (with some other sh(1) changes)
In particular, this makes things like ${#foo[0]} and ${#foo[@]} errors
rather than silent equivalents of ${#foo}.
PR: bin/151720
Submitted by: Mark Johnston
Exp-run done by: pav (with some other sh(1) changes)
For backgrounded pipelines and subshells, the previous value of $? was being
preserved, which is incorrect.
For backgrounded simple commands containing a command substitution, the
status of the last command substitution was returned instead of 0.
If fork() fails, this is an error.
If the -p option is turned off, privileges from a setuid or setgid binary
are dropped. Make sure to check if this succeeds. If it fails, this is an
error which will cause the shell to abort except in interactive mode or if
'command' was used to make 'set' or an outer 'eval' or '.' non-special.
Note that taking advantage of this feature and writing setuid shell scripts
seems unwise.
MFC after: 1 week
If EV_EXIT causes an exit, use the exception mechanism to unwind
redirections and local variables. This way, if the final command is a
redirected command, an EXIT trap now executes without the redirections.
Because of these changes, EV_EXIT can now be inherited by the body of a
function, so do so. This means that a function no longer prevents a fork
before an exec being skipped, such as in
f() { head -1 /etc/passwd; }; echo $(f)
Wrapping a single builtin in a function may still cause an otherwise
unnecessary fork with command substitution, however.
An exit command or -e failure still invokes the EXIT trap with the
original redirections and local variables in place.
Note: this depends on SHELLPROC being gone. A SHELLPROC depended on
keeping the redirections and local variables and only cleaning up the
state to restore them.
This is only a problem if IFS contains digits, which is unusual but valid.
Because of an incorrect fix for PR bin/12137, "${#parameter}" was treated
as ${#parameter}. The underlying problem was that "${#parameter}"
erroneously added CTLESC bytes before determining the length. This
was properly fixed for PR bin/56147 but the incorrect fix was not backed
out.
Reported by: Seeker on forums.freebsd.org
MFC after: 2 weeks
POSIX does not require the shell to fork for a subshell environment, and we
use that possibility in various ways (command substitutions with a single
command and most subshells that are the final command of a shell process).
Therefore do not tie subshells to forking in the man page.
Command substitutions with expansions are a bit strange, causing a fork for
$(...$(($x))...) because $x might expand to y=2; they will probably be
changed later but this is how they work now.
These already worked: $# ${#} ${##} ${#-} ${#?}
These now work as well: ${#+word} ${#-word} ${##word} ${#%word}
There is an ambiguity in the standard with ${#?}: it could be the length of
$? or it could be $# giving an error in the (impossible) case that it is not
set. We continue to use the former interpretation as it seems more useful.
New features:
* proper lazy evaluation of || and &&
* ?: ternary operator
* executable is considerably smaller (8K on i386) because lex and yacc are
no longer used
Differences from dash:
* arith_t instead of intmax_t
* imaxdiv() not used
* unset or null variables default to 0
* let/exp builtin (undocumented, will probably be removed later)
Obtained from: dash
* In {(...) <redir1;} <redir2, do not drop redir1.
* Maintain the difference between (...) <redir and {(...)} <redir:
In (...) <redir, the redirection is performed in the child, while in
{(...)} <redir it should be performed in the parent (like {(...); :;}
<redir)
POSIX requires this and it is simpler than the previous code that remembered
command locations when appending directories to PATH.
In particular,
PATH=$PATH
is no longer a no-op but discards all cached command locations.
If execve() returns an [ENOEXEC] error, check if the file is binary before
trying to execute it using sh. A file is considered binary if at least one
of the first 256 bytes is '\0'.
In particular, trying to execute ELF binaries for the wrong architecture now
fails with an "Exec format error" message instead of syntax errors and
potentially strange results.
These are called "shell procedures" in the source.
If execve() failed with [ENOEXEC], the shell would reinitialize itself
and execute the program as a script. This requires a fair amount of code
which is not frequently used (most scripts have a #! magic number).
Therefore just execute a new instance of sh (_PATH_BSHELL) to run the
script.
This matches the constants from <signal.h> with 'SIG' removed, which POSIX
requires kill and trap to accept and 'kill -l' to write.
'kill -l', 'trap', 'trap -l' output is now upper case.
In Turkish locales, signal names with an upper case 'I' are now accepted,
while signal names with a lower case 'i' are no longer accepted, and the
output of 'killall -l' now contains proper capital 'I' without dot instead
of a dotted capital 'I'.
* There is no plan for an alternative to the command "set".
* Attempting to unset a readonly variable has not raised an error for quite
a while, so the order of unsetting a variable and a function with the same
name does not matter.
MFC after: 1 week
When a foreground job exits on a signal, a message is printed to stdout
about this. The buffer was not flushed after this which could result in the
message being written to the wrong file if the next command was a builtin
and had stdout redirected.
Example:
sh -c 'kill -9 $$'; : > foo; echo FOO:; cat foo
Reported by: gcooper
MFC after: 1 week
This is useful so that it is easier to exit on a signal than to reset the
trap to default and resend the signal. It matches ksh93. POSIX says that
'exit' without args from a trap action uses the exit status from the last
command before the trap, which is different from 'exit $?' and matches this
if the previous command is assumed to have exited on the signal.
If the signal is SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU, or if the default
action for the signal is to ignore it, a normal _exit(2) is done with exit
status 128+signal_number.
* Make 'trap --' do the same as 'trap' instead of nothing.
* Make '--' stop option processing (note that '-' action is not an option).
Side effect: The error message for an unknown option is different.
All builtins are now always found before a PATH search.
Most ash derivatives have an undocumented feature where the presence of an
entry "%builtin" in $PATH will cause builtins to be checked at that point of
the PATH search, rather than before looking at any directories as documented
in the man page (very old versions do document this feature).
I am removing this feature from sh, as it complicates the code, may violate
expectations (for example, /usr/bin/alias is very close to a forkbomb with
PATH=/usr/bin:%builtin, only /usr/bin/builtin not being another link saves
it) and appears to be unused (all the %builtin google code search finds is
in some sort of ash source code).
Note that aliases and functions took and take precedence above builtins.
Because aliases work on a lexical level they can only ever be overridden on
a lexical level (quoting or preceding 'builtin' or 'command'). Allowing
override of functions via PATH does not really fit in the model of sh and it
would work differently from %builtin if implemented.
Note: POSIX says special builtins are found before functions. We comply to
this because we do not allow functions with the same name as a special
builtin.
Silence from: freebsd-hackers@ (message sent 20101225)
Discussed with: dougb
It should use the original exit status, just like falling off the
end of the trap handler.
Outside an EXIT trap, 'exit' is still equivalent to 'exit $?'.
An error message is written, the builtin is not executed, nonzero exit
status is returned but the shell does not abort.
This was already checked for special builtins and external commands, with
the same consequences except that the shell aborts for special builtins.
Obtained from: NetBSD
Change the criterion for builtins to be safe to execute in the same process
in optimized command substitution from a blacklist of only cd, . and eval to
a whitelist.
This avoids clobbering the main shell environment such as by $(exit 4) and
$(set -x).
The builtins jobid, jobs, times and trap can still show information not
available in a child process; this is deliberately permitted. (Changing
traps is not.)
For some builtins, whether they are safe depends on the arguments passed to
them. Some of these are always considered unsafe to keep things simple; this
only harms efficiency a little in the rare case they are used alone in a
command substitution.
If SIGINT arrived at exactly the right moment (unlikely), an exception
handler in a no longer active stack frame would be called.
Because the old handler was not used in the normal path, clang thought it
was a dead value and if an exception happened it would longjmp() to garbage.
This caused builtins/fc1.0 to fail if histedit.c was compiled with clang.
MFC after: 1 week
Before considering to execute a command substitution in the same process,
check if any of the expansions may have a side effect; if so, execute it in
a new process just like happens if it is not a single simple command.
Although the check happens at run time, it is a static check that does not
depend on current state. It is triggered by:
- expanding $! (which may cause the job to be remembered)
- ${var=value} default value assignment
- assignment operators in arithmetic
- parameter substitutions in arithmetic except ${#param}, $$, $# and $?
- command substitutions in arithmetic
This means that $((v+1)) does not prevent optimized command substitution,
whereas $(($v+1)) does, because $v might expand to something containing
assignment operators.
Scripts should not depend on these exact details for correctness. It is also
imaginable to have the shell fork if and when a side effect is encountered
or to create a new temporary namespace for variables.
Due to the $! change, the construct $(jobs $!) no longer works. The value of
$! should be stored in a variable outside command substitution first.
Command substitutions consisting of a single simple command are executed in
the main shell process but this should be invisible apart from performance
and very few exceptions such as $(trap).
Maintain a pointer to the end of the stack string area instead of how much
space is left. This simplifies the macros in memalloc.h. The places where
the new variable must be updated are only where the memory area is created,
destroyed or resized.
This allows specifying a %job (which is equivalent to the corresponding
process group).
Additionally, it improves reliability of kill from sh in high-load
situations and ensures "kill" finds the correct utility regardless of PATH,
as required by POSIX (unless the undocumented %builtin mechanism is used).
Side effect: fatal errors (any error other than kill(2) failure) now return
exit status 2 instead of 1. (This is consistent with other sh builtins, but
not in NetBSD.)
Code size increases about 1K on i386.
Obtained from: NetBSD
The #define for warnx now behaves much like the libc function (except that
it uses sh command name and output).
Also, it now uses C99 __VA_ARGS__ so there is no need for three different
macros for 0, 1 or 2 parameters.
Constants in arithmetic starting with 0 should be octal only.
This avoids the following highly puzzling result:
$ echo $((018-017))
3
by making it an error instead.
c is assigned 0 and *loc is pointing to NULL, so c!=0 cannot be true,
and dereferencing loc would be a bad idea anyway.
Coverity Prevent: CID 5113
Reviewed by: jilles
The CTLESC byte to protect a special character was output before instead of
after a newline directly preceding the special character.
The special handling of newlines is because command substitutions discard
all trailing newlines.
* Prefer kill(-X) to killpg(X).
* Remove some dead code.
* No additional SIGINT is needed if int_pending() is already true.
No functional change is intended.
The herefd hack wrote out partial here documents while expanding them. It
seems unnecessary complication given that other expansions just allocate
memory. It causes bugs because the stack is also used for intermediate
results such as arithmetic expressions. Such places should disable herefd
for the duration but not all of them do, and I prefer removing the need for
disabling herefd to disabling it everywhere needed.
Here documents larger than 1024 bytes will use a bit more CPU time and
memory.
Additionally this allows a later change to expand here documents in the
current shell environment. (This is faster for small here documents but also
changes behaviour.)
Obtained from: dash
The code to translate the internal representation to text did not know about
various additions to the internal representation since the original ash and
therefore wrote binary stuff to the terminal.
The code is used in the jobs command and similar output.
Note that the output is far from complete and mostly serves for recognition
purposes.
If describing the status of a pipeline, write all elements of the pipeline
and show the status of the last process (which would also end up in $?).
Only write one report per job, not one for every process that exits.
To keep some earlier behaviour, if any process started by the shell in a
foreground job terminates because of a signal, write a message about the
signal (at most one message per job, however).
Also, do not write messages about signals in the wait builtin in
non-interactive shells. Only true foreground jobs now write such messages
(for example, "Terminated").
In r208489, I added code to reap zombies when forking new processes, to
limit the amount of zombies. However, this can lead to marking a job as done
or stopped if it consists of multiple processes and the first process ends
very quickly. Fix this by only checking for zombies before forking the first
process of a job and not marking any jobs without processes as done or
stopped.
The getpgid() call will fail if the first process in the job has already
terminated, resulting in output of "-1".
The pgid of a job is always the pid of the first process in the job and
other code already relies on this.
Make sure all built-in commands are in the subsection named such, except
exp, let and wordexp which are deliberately undocumented. The text said only
built-ins that really need to be a built-in were documented there but in
fact almost all of them were already documented.
* Prefer one CHECKSTRSPACE with multiple USTPUTC to multiple STPUTC.
* Add STPUTS macro (based on function) and use it instead of loops that add
nul-terminated strings to the stack string.
No functional change is intended, but code size is about 1K less on i386.
If getcwd fails, do not treat this as an error, but print a warning and
unset PWD. This is similar to the behaviour when starting the shell in a
directory whose name cannot be determined.
Since is_alpha/is_name/is_in_name were made ASCII-only, this can no longer
happen.
Additionally, the check was wrong because it did not include the new
CTLQUOTEEND.
This was removed in 2001 but I think it is appropriate to add it back:
* I do not want to encourage people to write fragile and non-portable echo
commands by making printf much slower than echo.
* Recent versions of Autoconf use it a lot.
* Almost no software still wants to support systems that do not have
printf(1) at all.
* In many other shells printf is already a builtin.
Side effect: printf is now always the builtin version (which behaves
identically to /usr/bin/printf) and cannot be overridden via PATH (except
via the undocumented %builtin mechanism).
Code size increases about 5K on i386. Embedded folks might want to replace
/usr/bin/printf with a hard link to /usr/bin/alias.
The information in sh(1) about the echo builtin is equivalent, though less
extensive.
The echo(1) man page (bin/echo/echo.1) is different.
Unfortunately, sh's echo builtin and /bin/echo have gone out of sync and
this probably cannot be fixed any more.
Reported by: uqs (list of untouched files)
MFC after: 1 week
In particular, remove the text about ksh-like features, which are usually
taken for granted nowadays. The original Bourne shell is fading away and for
most users our /bin/sh is one of the most minimalistic they know.
Convert the tests to the perl prove format.
Remove obsolete TEST.README (results of an old TEST.sh for some old Unices)
and TEST.csh (old tests without correct values, far less complete than
TEST.sh).
MFC after: 1 week
This moves the function of the noaliases variable into the checkkwd
variable. This way it is properly reset on errors and aliases can be used
normally in the commands for each case (the case labels recognize the
keyword esac but no aliases).
The new code is clearer as well.
Obtained from: dash
I've noticed various terminal emulators that need to obtain a sane
default termios structure use very complex `hacks'. Even though POSIX
doesn't provide any functionality for this, extend our termios API with
cfmakesane(3), which is similar to the commonly supported cfmakeraw(3),
except that it fills the termios structure with sane defaults.
Change all code in our base system to use this function, instead of
depending on <sys/ttydefaults.h> to provide TTYDEF_*.
These do something else in ksh: name=(...) is an array or compound variable
assignment and the others are extended patterns.
This is the last patch of the ones tested in the exp run.
Exp-run done by: pav (with some other sh(1) changes)
Apart from detecting breakage earlier or at all, this also fixes a segfault
in the testsuite. The "handling" of the breakage left an invalid internal
representation in some cases.
Examples:
echo a; do echo b
echo `) echo a`
echo `date; do do do`
Exp-run done by: pav (with some other sh(1) changes)
subevalvar() incorrectly assumed that CTLESC bytes were present iff the
expansion was quoted. However, they are present iff various processing such
as word splitting is to be done later on.
Example:
v=@$e@$e@$e@
y="${v##*"$e"}"
echo "$y"
failed if $e contained the magic CTLESC byte.
Exp-run done by: pav (with some other sh(1) changes)
The code is inspired by NetBSD sh somewhat, but different because we
preserve the old Almquist/Bourne/Korn ability to have an unquoted part in a
quoted ${v+word}. For example, "${v-"*"}" expands to $v as a single field if
v is set, but generates filenames otherwise.
Note that this is the only place where we split text literally from the
script (the similar ${v=word} assigns to v and then expands $v). The parser
must now add additional markers to allow the expansion code to know whether
arbitrary characters in substitutions are quoted.
Example:
for i in ${$+a b c}; do echo $i; done
Exp-run done by: pav (with some other sh(1) changes)
If double-quote state does not match, treat the '}' literally.
This ensures double-quote state remains the same before and after a
${v+-=?...} which helps with expand.c.
It makes things like
${foo+"\${bar}"}
which I have seen in the wild work as expected.
Exp-run done by: pav (with some other sh(1) changes)
This is a syntax error.
POSIX does not say explicitly whether defining a function with the same name
as a special builtin is allowed, but it does say that it is impossible to
call such a function.
A special builtin can still be overridden with an alias.
This commit is part of a set of changes that will ensure that when
something looks like a special builtin to the parser, it is one. (Not the
other way around, as it remains possible to call a special builtin named
by a variable or other substitution.)
Exp-run done by: pav (with some other sh(1) changes)
Add some conservative checks on function names:
- Disallow expansions or quoting characters; these can only be called via
strange control characters
- Disallow '/'; these functions cannot be called anyway, as exec.c assumes
they are pathnames
- Make the CTL* bytes work properly in function names.
These are syntax errors.
POSIX does not require us to support more than names (letters, digits and
underscores, not starting with a digit), but I do not want to restrict it
that much at this time.
Exp-run done by: pav (with some other sh(1) changes)
This is how ksh93 treats ! within a pipeline and makes the ! in
a | ! b | c
negate the exit status of the pipeline, as if it were
a | { ! b | c; }
Side effect: something like
f() ! a
is now a syntax error, because a function definition takes a command,
not a pipeline.
Exp-run done by: pav (with some other sh(1) changes)
For multi-command pipelines,
1. all commands are direct children of the shell (unlike the original
Bourne shell)
2. all commands are executed in a subshell (unlike the real Korn shell)
MFC after: 1 week
immediately written into the stack after the call. Instead let the caller
manage the "space left".
Previously, growstackstr()'s assumption causes problems with STACKSTRNUL()
where we want to be able to turn a stack into a C string, and later
pretend the NUL is not there.
This fixes a bug in STACKSTRNUL() (that grew the stack) where:
1. STADJUST() called after a STACKSTRNUL() results in an improper adjust.
This can be seen in ${var%pattern} and ${var%%pattern} evaluation.
2. Memory leak in STPUTC() called after a STACKSTRNUL().
Reviewed by: jilles
- Use %t to print ptrdiff_t values.
- Cast a ptrdiff_t value explicitly to int for a field width specifier.
While here, sort includes.
Submitted by: Garrett Cooper
frobbing CFLAGS directly. DEBUG_FLAGS is something that can be specified
on the make command line without having to edit the Makefile directly.
Submitted by: Garrett Cooper
Add directory names directly and sort at the end.
Include bsd.arch.inc.mk so we can, in the future, more easily make arch
dependent changes in /bin (unlikely, but is needed for symmetry).
expr(1) should usually not be used as various forms of parameter expansion
and arithmetic expansion replicate most of its functionality in an easier
way.
getopt(1) should not be used at all in new code. Instead, getopts(1) or
entirely manual parsing should be used.
MFC after: 1 week
The three examples are better done using sh(1) itself these days.
The example
expr -- "$a" : ".*"
is incorrect in the general case, as "$a" may be an operator.
MFC after: 2 weeks
This makes it impossible to use locale-specific characters in variable
names.
Names containing locale-specific characters make scripts only work with the
correct locale setting. Also, they did not even work in many practical cases
because multibyte character sets such as utf-8 are not supported.
This also avoids weirdness if LC_CTYPE is changed in the middle of a script.
are too long. Filenames escaping this test are caught later on,
so the bug doesn't cause any breakage.
Document the correct ustar limitations in pax. As I have no access
to the IEEE 1003.2 spec, I can only assume that the limitations
imposed are in fact correct.
Add regression tests for the filename limitations imposed by pax.
MFC after: 3 weeks
This Almquist extension was disabled long ago.
In pathname generation, components starting with '!!' were treated as
containing wildcards, causing unnecessary readdir (which could fail, causing
pathname generation to fail while it should not).
In our implementation and most others, a break or continue in a dot script
can break or continue a loop outside the dot script. This should cause all
further commands in the dot script to be skipped. However, cmdloop() did not
know about this and continued to parse and execute commands from the dot
script.
As described in the man page, a return in a dot script in a function returns
from the function, not only from the dot script. There was a similar issue
as with break and continue. In various other shells, the return appears to
return from the dot script, but POSIX seems not very clear about this.
The buffer for generated pathnames could be too small in some cases. It
happened to be always at least PATH_MAX long, so there was never an overflow
if the resulting pathnames would be usable.
This bug may be abused if a script subjects input from an untrusted source
to pathname generation, which a bad idea anyhow. Most shell scripts do not
work on untrusted data. secteam@ says no advisory is necessary.
PR: bin/148733
Reported by: Changming Sun snnn119 at gmail com
MFC after: 10 days
This makes a difference if there is a command substitution.
To make this work, evalstring() has been changed to set exitstatus to 0 if
no command was executed (the string contained only whitespace).
Example:
eval $(false); echo $?
should print 0.
refusing to use stdio.
Reduce nesting level in the sleep loop by returning earlier for negative
timeouts.
Limit the maximum timeout to INT_MAX seconds.
Submitted by: bde
MFC after: 3 weeks
This simply sets a flag in libedit. It has a shortcoming in that it does not
apply to multi-line commands.
Note that a configuration option for this is not going to happen, but always
having this seems better than not having it. NetBSD has done the same.
PR: bin/54683
Obtained from: NetBSD
MFC after: 1 month
So a command like
kill _HUP 1
now fails without sending SIGTERM to init.
The behaviour when kill(2) fails remains unchanged: processing continues.
This matches other implementations and POSIX and is useful for killing
multiple processes at once when some of them may already be gone.
PR: bin/40282
If an ; or & token was followed by an EOF token, pending here-documents were
left uninitialized. Execution would crash, either in the main shell process
for literal here-documents or in a child process for expanded
here-documents. In the latter case the problem is hard to detect apart from
the core dumps and log messages.
Side effect: slightly different retries on inputs where EOF is not
persistent.
Note that tools/regression/bin/sh/parser/heredoc6.0 still causes a similar
crash in a child process. The text passed to eval is malformed and should be
rejected.
simplecmd() only handles simple commands and function definitions, neither
of which involves the ! keyword. The initial token on entry to simplecmd()
is one of the following: TSEMI, TAND, TOR, TNL, TEOF, TWORD, TRP.
Unless $! has been referenced for a particular job or $! still contains that
job's pid, forget about it after it has terminated. If $! has been
referenced, remember the job until the wait builtin has reported its
completion (either with the pid as parameter or without parameters).
In interactive mode, jobs are forgotten after termination has been reported,
which happens before primary prompts and through the jobs builtin. Even
then, though, remember a job if $! has been referenced.
This is similar to what is suggested by POSIX and should fix most memory
leaks (which also tend to cause sh to use more CPU time) with long running
scripts that start background jobs.
Caveats:
* Repeatedly referencing $! without ever doing 'wait', like
while :; do foo & echo started foo: $!; sleep 60; done
will still use a lot of memory and CPU time in the long run.
* The jobs and jobid builtins do not cause a job to be remembered for longer
like expanding $! does.
PR: bin/55346
The LINENO code uses snprintf() and relied on "myhistedit.h" to pull in the
necessary <stdio.h>.
Compiling with -DNO_HISTORY disables all editing and history support and
allows linking without -ledit -ltermcap. This may be useful for embedded
systems.
MFC after: 2 weeks
This uses the new libedit completion function with quoting support.
Unlike NetBSD, there is no 'set +o tabcomplete' option to disable
completion. I do not see any reason for such a special treatment, as
completion is rather useful and it is possible to do
bind ^I ed-insert
to disable completion and insert a tab character instead.
Submitted by: Guy Yur
- .Nd in section NAME is not optional
- .Ed was missing
- "indent" is not a flag, but a literal argument for -offset
- stop switching font sizes for acronyms
- use .Brq instead of rolling our own
is enabled.
This already worked if without job control.
In either case, this depends on it that a process that terminates due to
SIGINT exits on it (so not with status 1, or worse, 0).
Example:
sleep 5; echo continued
This does not print "continued" any more if sleep is aborted via ctrl+c.
MFC after: 1 month
Previously, it would either try to copy it anyway and fail (without -R),
or create fifo instead of the socket (with -R).
Found with: Coverity Prevent
CID: 5623
MFC after: 2 weeks
usually be set first when using -v.
Adjust an example that sets the day to 30 before setting the month to 3 in
accordance with this approach as the example would always fail in February!
PR: 147354
MFC after: 2 weeks
Example (in interactive mode):
cat <<EOF && )
The next command typed caused sh to segfault, because the state for the here
document was not reset.
Like parser_temp, this uses the fact that the parser is not re-entered.
If a command substitution contains a newline token, this no longer starts
here documents of outer commands. This way, we follow POSIX's idea of the
command substitution being a separate script more closely. It also matches
other shells better and is consistent with newline characters in quotes not
starting here documents.
The extension tested in parser/heredoc3.0 ($(cat <<EOF)\ntext\nEOF\n)
continues to be supported.
In particular, this change allows things like
cat <<EOF && echo `pwd`
(a `` command substitution after a here document)
which formerly silently used an empty file as the here document, because the
EOF of the inner command "pwd" also forced an empty here document.
Although "--" historically has not been required to be recognized for
certain special builtins that do not take options in POSIX, some other
implementations recognize options for them, requiring scripts to use "--" or
avoid operands starting with "-".
Operands starting with "-" can be avoided with eval by prepending a space,
and cannot occur with break, continue, exit, return and shift as they only
take numbers, nor with times as it does not take operands. With . and exec,
avoiding "-" is not so easy as it may require reimplementing the PATH
search; therefore the current proposal for POSIX is to require recognition
of "--" for them.
We continue to accept other strings starting with "-" as operands to . and
exec, and also "--" if it is alone to . (which would otherwise be invalid
anyway).
* Move the "environment variables" that do not need exporting to be
effective or that are set by the shell without exporting to a new section
"Special Variables".
* Add special variables LINENO and PPID.
* Add environment variables LANG, LC_* and PWD; also describe ENV under
environment variables.
This prevents accumulating huge amounts of zombies if a script executes
many background commands but no external commands or subshells.
Note that zombies will not be reaped during long calculations (within
the shell process) or read builtins, but those actions do not create
more zombies.
The terminated background commands will also still be remembered by the
shell.
PR: bin/55346
pax(1) was trying to copy the back-referenced data from
the match pattern, not the matched data.
PR: bin/118132
Obtained from: Debian bug #451361
Reviewed by: jilles
MFC after: 3 weeks
These are git commits 36f0fa8fcbc8c7b2b194addd29100fb40e73e4e9 and
d6d06ff5c2ea0fa44becc5ef4340e5f2f15073e4 in dash.
Because this is the first code I'm importing from dash to expand.c, add the
Herbert Xu copyright notice which is in dash's expand.c.
When pathname expanding *\/, the CTLESC representing the quoted state was
erroneously taken as part of the * pathname component. This CTLESC was then
seen by the pattern matching code as escaping the '\0' terminating the
string.
The code is slightly different because dash converts the CTLESC characters
to backslashes and removes all the other CTL* characters to allow
substituting glob(3).
The effect of the bug was also slightly different from dash (where nothing
matched at all). Because a CTLESC can escape a '\0' in some way, whether
files were included despite the bug depended on memory that should not be
read. In particular, on many machines /*\/ expanded to a strict subset of
what /*/ expanded to.
Example:
echo /*"/null"
This should print /dev/null, not /*/null.
PR: bin/146378
Obtained from: dash
This allows doing things like LC_ALL=C some_builtin to run a builtin under a
different locale, just like is possible with external programs. The
immediate reason is that this allows making printf(1) a builtin without
breaking things like LC_NUMERIC=C printf '%f\n' 1.2
This change also affects special builtins, as even though the assignment is
persistent, the export is only to the builtin (unless the variable was
already exported).
Note: for this to work for builtins that also exist as external programs
such as /bin/test, the setlocale() call must be under #ifndef SHELL. The
shell will do the setlocale() calls which may not agree with the environment
variables.
in at least three ways, so do not say it is ignored:
* who may delete/rename a symlink in a sticky directory
* who may do lchflags(2)/lchown(2)/lchmod(2)
* whose inode quota is charged
MFC after: 1 week
In the 'ln source... directory' synopsis, the basename of each source
determines the name of the created link. Determine this using basename(3)
instead of strrchr(..., '/') which is incorrect if the pathname ends in a
slash.
The patch is somewhat changed to allow for basename(3) implementations that
change the passed pathname, and to fix the -w option's checking also.
The code to compare directory entries only applies to hard links, which
cannot be created to directories using ln.
Example:
ln -s /etc/defaults/ /tmp
This should create a symlink named defaults.
PR: 121568
Submitted by: Ighighi
MFC after: 1 week
Two pathnames refer to the same directory entry iff the directories match
and the final components' names match.
Example: (assuming file1 is an existing file)
ln -f file1 file1
This now fails while leaving file1 intact. It used to delete file1 and then
complain it cannot be linked because it is gone.
With -i, this error is detected before the question is asked.
MFC after: 2 weeks
Unset PWD if it is incorrect and no value for it can be determined.
This preserves the logical current directory across shell invocations.
Example (assuming /home is a symlink):
$ cd
$ pwd
/home/foo
$ sh
$ pwd
/home/foo
Formerly the second pwd would show the physical path (symlinks resolved).
Although groff_mdoc(7) gives another impression, this is the ordering
most widely used and also required by mdocml/mandoc.
Reviewed by: ru
Approved by: philip, ed (mentors)
These do pretty much nothing (except that parentheses are ignored), but
people seem to use them and allowing them does not hurt much.
Single-quotes seem not to be used and cause silently different behaviour
with ksh93 character constants.
This makes sh a bit more friendly in single user mode, make buildenv, chroot
and the like, and matches other shells.
The -o emacs can be overridden on the command line or in the ENV file.
Note that the following sentence
> Enclosing the full parameter expansion string in double-quotes does not
> cause the following four varieties of pattern characters to be quoted,
> whereas quoting characters within the braces has this effect.
is now true, but used to be incorrect.
This applies to word in ${v-word}, ${v+word}, ${v=word}, ${v?word} (which
inherits quoting from the outside) and in ${v%word}, ${v%%word}, ${v#word},
${v##word} (which does not inherit any quoting).
In all cases tilde expansion is only attempted at the start of word, even if
word contains spaces. This agrees with POSIX and other shells.
This is the last part of the patch tested in the exp-run.
Exp-run done by: erwin (with some other sh(1) changes)
Note that this depends on r206145 for allowing pattern match characters to
have their special meaning inside a double-quoted expansion like "${v%pat}".
PR: bin/117748
Exp-run done by: erwin (with some other sh(1) changes)
They will be treated like normal characters, resulting in a runtime
arithmetic expression error.
Exp-run done by: erwin (with some other sh(1) changes)
* remove the backslash from \} inside double quotes inside +-=?
substitutions, e.g. "${$+\}a}"
* maintain separate double-quote state for ${v#...} and ${v%...};
single and double quotes are special inside, even in a double-quoted
string or here document
* keep track of correct order of substitutions and arithmetic
This is different from dash's approach, which does not track individual
double quotes in the parser, trying to fix this up during expansion.
This treats single quotes inside "${v#...}" incorrectly, however.
This is similar to NetBSD's approach (as submitted in PR bin/57554), but
recognizes the difference between +-=? and #% substitutions hinted at in
POSIX and is more refined for arithmetic expansion and here documents.
PR: bin/57554
Exp-run done by: erwin (with some other sh(1) changes)
The old approach was wrong because PS2 was not used and seems unlikely to
parse extensions (ksh93's ${ COMMAND} may well fail to parse).
Exp-run done by: erwin (with some other sh(1) changes)
Redirection errors on subshells already did not abort the shell because
the redirection is executed in the subshell.
Other shells seem to agree that these redirection errors should not abort
the shell.
Also ensure that the redirections will be cleaned up properly in cases like
command eval '{ shift x; } 2>/dev/null'
Example:
{ echo bad; } </var/empty/x; echo good
Although simple commands without a command word (only assignments and/or
redirections) are much like special builtins, POSIX and most shells seem to
agree that redirection errors should not abort the shell in this case. Of
course, the assignments persist and assignment errors are fatal.
To get the old behaviour portably, use the ':' special builtin.
To get the new behaviour portably, given that there are no assignments, use
the 'true' regular builtin.
Make parsebackq a function instead of an emulated nested function.
This puts the setjmp usage in a smaller function where it is easier to avoid
bad optimizations.
* avoid unnecessary fork
* allow executing builtins via command
* executing a special builtin via command removes its special properties
Obtained from: NetBSD (parts)
Although argc and argv are never read after the longjmp is complete,
gcc is not clever enough to see that and needlessly warns about it.
So add volatile to silence the compiler.
Approved by: ed (the co-mentor, not ed(1))
Otherwise the -i option will show the inode number of the referenced file
for symbolic links given on the command line. Similarly, the file color
was printed according to the link target in colorized output.
PR: bin/102394
Reviewed by: jilles
MFC after: 2 weeks
All the elements of these structs are char anyway, so it won't hurt
performance.
Bump warns back up to the default.
# we likely should have CTASSERTS to make sure they are the right size.
# but with libarchive based tar maybe we shouldn't bother.
- Allow -h option to work if the listing contains at least one device
file.
- Align major and minor device numbers correctly to the size field.
PR: bin/125678
Approved by: trasz (mentor)
MFC after: 1 month
provides an empty fts_name and reporting the full path is more
appropriate especially with the -R option.
PR: bin/107515
Submitted by: bde
Approved by: trasz (mentor)
MFC after: 1 week
feature parity with du(1) and similar: When set, cp(1) will not traverse
mount points.
Initial patch by: Graham J Lee leeg teaching.physics.ox.ac.uk
PR: bin/88056
Initial patch by: Graham J Lee leeg teaching.physics.ox.ac.uk
Approved by: ed (mentor)
MFC after: 1 month
csh allows you to monitor the utmp(x) file to monitor certain user
logins. Unfortunately it needs to directly stat() this file. I don't
want to break this module , but eventually it shouldn't do that. The
idea of the getutxent(3) API is to hide file access.
Approved by: mp
functionality. Per the regression tests (pgrep-t.t & pkill-t.t), "-t"
should accept "v1", which means a plain number should be accepted for
UNIX98-style PTY's.
- correctly handle error output in $(builtin 2>&1), clarify out1/out2 vs
output/errout in the code
- treat all builtins as regular builtins so errors do not abort the shell
and variable assignments do not persist
- respect the caller's INTOFF
Some bugs still exist:
- expansion errors may still abort the shell
- some side effects of expansions and builtins persist
This will be important when things like 'command eval f' will be possible.
Currently, the funcnest = 0 assignment in RESET (called when returning to
the top level after an error in interactive mode) is really sufficient.
Fix some wrong usages.
Note: this does not affect generated binaries as this argument is not used.
PR: 137213
Submitted by: Eygene Ryabinkin (initial version)
MFC after: 1 month
Reset the exception handler in the child to main's.
This avoids inappropriate double cleanups or shell duplication when the
exception is caught, such as 'fc' and future 'command eval' and 'command .'.
That is, do not do tilde expansion if any of the CTL* bytes (\201-\210), not
only CTLESC and CTLQUOTEMARK, are encountered. Such an expansion would look
up a user name with sh's internal representation.
The parser does not currently distinguish between backslashed and
unbackslashed \201-\210, so tilde expansion of user names with these bytes
in them is not so easy to fix.
It is already done by evalcommand(), unless special-ness has been removed,
in which case variable assignments should not persist. (These are currently
always special builtins, but this will change later: command builtin,
command substitution.)
This also fixes a memory leak when calling . with variable assignments.
Example:
valgrind --leak-check=full sh -c 'x=1 . /dev/null; x=2'
- Redirecting fds that were not open before kept two copies of the
redirected file.
sh -c '{ :; } 7>/dev/null; fstat -p $$; true'
(both fd 7 and 10 remained open)
- File descriptors used to restore things after redirection were not
set close-on-exec, instead they were explicitly closed before executing
a program normally and before executing a shell procedure. The latter
must remain but the former is replaced by close-on-exec.
sh -c 'exec 7</; { exec fstat -p $$; } 7>/dev/null; true'
(fd 10 remained open)
The examples above are simpler than the testsuite because I do not want to
use fstat or procstat in the testsuite.
* exception handlers are now run with interrupts disabled, which avoids
many race conditions
* fix some cases where SIGINT only aborts one command and continues the
script, in particular if a SIGINT causes an EINTR error which trumped the
interrupt.
Example:
sh -c 'echo < /some/fifo; echo This should not be printed'
The fifo should not have writers. When pressing ctrl+c to abort the open,
the shell used to continue with the next command.
Example:
sh -c '/bin/echo < /some/fifo; echo This should not be printed'
Similar. Note, however, that this particular case did not and does not work
in interactive mode with job control enabled.
This avoids weirdness when 'fc -e vi' or the like is done and there is a
syntax error in the file. Formerly an interactive shell tried to execute
stuff after the syntax error and exited.
This should also avoid similar issues with 'command eval' and 'command .'
when 'command' is implemented properly as in NetBSD sh.
Special builtins did not have this problem since errors in them cause the
shell to exit or to reset various state such as the current command input
file.
* increase buffer size from 100 to 256 bytes
* remove implied flush from out2str(), in particular this avoids unnecessary
flushing in the middle of a -x tracing line
* rename dprintf() to out2fmt_flush(), make it flush out2 and use this
function in various places where flushing is desired after an error
message
This is similar to the Solaris utility of the same name.
Some use cases:
* rc.subr's wait_for_pids
* interactive use, e.g. to shut down the computer when some task is done
even if the task is already running
Discussed on: hackers@
This seems more useful and will likely be in the next POSIX standard.
Also document more precisely in the man page what set -u does (note that
$@, $* and $! are the only special parameters that can ever be unset, all
the others are always set, although they may be empty).
the line number where the command substitution started.
This applies to both the $() and `` forms but is most useful for ``
because the other line number is relative to the enclosed text there.
(For older versions, -v can be used as a workaround.)