mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Add ${.sh.ppid} (re: 48f78227
)
Since we now have sh.current_ppid, we might as well point a shell variable to it, as the cost is nil. Together, ${.sh.pid} and ${.sh.ppid} (updated when a virtual subshell forks) form a logical counterpart pair to $$ and $PPID (never updated in subshells). This commit also adds a section to the manual page that hopefully does away with the depressingly widespread subshell/child shell confusion once and for all... :P
This commit is contained in:
parent
305073af9d
commit
1a0d75d47c
5 changed files with 91 additions and 16 deletions
|
@ -103,6 +103,7 @@ const struct shtable2 shtab_variables[] =
|
||||||
".sh.math", 0, (char*)0,
|
".sh.math", 0, (char*)0,
|
||||||
".sh.pool", 0, (char*)0,
|
".sh.pool", 0, (char*)0,
|
||||||
".sh.pid", NV_PID|NV_NOFREE, (char*)0,
|
".sh.pid", NV_PID|NV_NOFREE, (char*)0,
|
||||||
|
".sh.ppid", NV_PID|NV_NOFREE, (char*)0,
|
||||||
".sh.tilde", 0, (char*)0,
|
".sh.tilde", 0, (char*)0,
|
||||||
"SHLVL", NV_INTEGER|NV_NOFREE|NV_EXPORT, (char*)0,
|
"SHLVL", NV_INTEGER|NV_NOFREE|NV_EXPORT, (char*)0,
|
||||||
"", 0, (char*)0
|
"", 0, (char*)0
|
||||||
|
|
|
@ -113,7 +113,8 @@ extern void sh_save_rand_seed(struct rand *, int);
|
||||||
#define SH_MATHNOD (sh.bltin_nodes+61)
|
#define SH_MATHNOD (sh.bltin_nodes+61)
|
||||||
#define SH_JOBPOOL (sh.bltin_nodes+62)
|
#define SH_JOBPOOL (sh.bltin_nodes+62)
|
||||||
#define SH_PIDNOD (sh.bltin_nodes+63)
|
#define SH_PIDNOD (sh.bltin_nodes+63)
|
||||||
#define SH_TILDENOD (sh.bltin_nodes+64)
|
#define SH_PPIDNOD (sh.bltin_nodes+64)
|
||||||
#define SHLVL (sh.bltin_nodes+65)
|
#define SH_TILDENOD (sh.bltin_nodes+65)
|
||||||
|
#define SHLVL (sh.bltin_nodes+66)
|
||||||
|
|
||||||
#endif /* SH_VALNOD */
|
#endif /* SH_VALNOD */
|
||||||
|
|
|
@ -192,9 +192,9 @@ shell option is on)
|
||||||
by a
|
by a
|
||||||
.IR pipe (2)
|
.IR pipe (2)
|
||||||
to the standard input of the next command.
|
to the standard input of the next command.
|
||||||
Each command,
|
Each command except the last is run asynchronously in a subshell (see
|
||||||
except possibly the last,
|
.I Subshells\^
|
||||||
is run as a separate process.
|
below).
|
||||||
If the
|
If the
|
||||||
.B monitor
|
.B monitor
|
||||||
or
|
or
|
||||||
|
@ -562,7 +562,9 @@ status is 0, otherwise the exit status is 1.
|
||||||
.br
|
.br
|
||||||
Execute
|
Execute
|
||||||
.I list\^
|
.I list\^
|
||||||
in a separate environment.
|
in a subshell (see
|
||||||
|
.I Subshells\^
|
||||||
|
below).
|
||||||
Note, that if two adjacent open parentheses are
|
Note, that if two adjacent open parentheses are
|
||||||
needed for nesting, a space must be inserted to avoid
|
needed for nesting, a space must be inserted to avoid
|
||||||
evaluation as an arithmetic command as described above.
|
evaluation as an arithmetic command as described above.
|
||||||
|
@ -927,6 +929,55 @@ If this value is non-empty and does not start with a
|
||||||
.BR \(ap ,
|
.BR \(ap ,
|
||||||
it replaces the default tilde expansion when the function terminates.
|
it replaces the default tilde expansion when the function terminates.
|
||||||
Otherwise, the tilde expansion is left unchanged.
|
Otherwise, the tilde expansion is left unchanged.
|
||||||
|
.SS Subshells.
|
||||||
|
A
|
||||||
|
.I subshell\^
|
||||||
|
is a separate execution environment that is a complete duplicate of the
|
||||||
|
current shell environment, except for two things: all traps are reset to
|
||||||
|
default except those for signals that are being ignored, and subshells
|
||||||
|
cannot be interactive (i.e., they have no command prompt).
|
||||||
|
Changes made within a subshell do not affect the parent environment and are
|
||||||
|
lost when the subshell exits.
|
||||||
|
.PP
|
||||||
|
Particular care should be taken not to confuse a subshell with a newly
|
||||||
|
invoked shell that is merely a child process of the current shell,
|
||||||
|
and which (unlike a subshell) starts from scratch in terms of
|
||||||
|
variables and functions and may be interactive.
|
||||||
|
Beware of shell tutorials on the Internet that confuse these.
|
||||||
|
.PP
|
||||||
|
Subshells are not themselves invoked as commands.
|
||||||
|
Instead, the following are automatically run in or from a subshell:
|
||||||
|
.RS 8
|
||||||
|
.IP \[bu] 3
|
||||||
|
any command or group of commands enclosed in parentheses;
|
||||||
|
.IP \[bu]
|
||||||
|
command substitutions of the first and third form (see
|
||||||
|
.I "Command Substitution"
|
||||||
|
below);
|
||||||
|
.IP \[bu]
|
||||||
|
process substitutions (see
|
||||||
|
.I "Process Substitution"
|
||||||
|
below);
|
||||||
|
.IP \[bu]
|
||||||
|
all elements of a pipeline except the last;
|
||||||
|
.IP \[bu]
|
||||||
|
any command executed asynchronously (i.e., in a background process).
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
Creating processes is expensive, so as a performance optimization, a
|
||||||
|
subshell of a non-interactive shell may share the process of its parent
|
||||||
|
environment. Such a subshell is known as a virtual subshell.
|
||||||
|
Subshells are virtual unless or until something (such as asynchronous
|
||||||
|
execution, or an attempt to set a process limit using the
|
||||||
|
.B ulimit
|
||||||
|
built-in command, or other implementation- or system-defined requirements)
|
||||||
|
makes it necessary to fork it into a separate process.
|
||||||
|
Barring any bugs in the shell, virtual subshells should be indistinguishable
|
||||||
|
from real subshells except by their execution speed and their process ID.
|
||||||
|
See the description of the
|
||||||
|
.B .sh.pid
|
||||||
|
variable below for more information.
|
||||||
|
.RE
|
||||||
.SS Command Substitution.
|
.SS Command Substitution.
|
||||||
The standard output from a command list enclosed in
|
The standard output from a command list enclosed in
|
||||||
parentheses preceded by a dollar sign (
|
parentheses preceded by a dollar sign (
|
||||||
|
@ -1614,7 +1665,8 @@ that run in the current environment may return status values in this range.
|
||||||
.B $
|
.B $
|
||||||
The process ID of the main shell process. Note that this value will not
|
The process ID of the main shell process. Note that this value will not
|
||||||
change in a subshell, even if the subshell runs in a different process.
|
change in a subshell, even if the subshell runs in a different process.
|
||||||
See also \f3.sh.pid\fP.
|
See also
|
||||||
|
.BR .sh.pid .
|
||||||
.TP
|
.TP
|
||||||
.B _
|
.B _
|
||||||
Initially, the value of
|
Initially, the value of
|
||||||
|
@ -1783,14 +1835,30 @@ discipline function is invoked.
|
||||||
The current depth for subshells and command substitution.
|
The current depth for subshells and command substitution.
|
||||||
.TP
|
.TP
|
||||||
.B .sh.pid
|
.B .sh.pid
|
||||||
Set to the process ID of the current shell.
|
Set to the process ID of the current shell process.
|
||||||
This is distinct from
|
Unlike
|
||||||
.B $$
|
.BR $$ ,
|
||||||
as in forked subshells this is set to the process ID of the
|
this is updated in a subshell when it forks into a new process.
|
||||||
subshell instead of the parent shell's process ID.
|
Note that a virtual subshell may have to fork mid-execution
|
||||||
In virtual subshells
|
due to various system- and implementation-dependent requirements,
|
||||||
|
so the value should not be counted on to remain the same
|
||||||
|
from one command to the next.
|
||||||
|
If a persistent process ID is required for a subshell,
|
||||||
|
it must be ensured it is running in its own process first.
|
||||||
|
Any attempt to set a process limit using the
|
||||||
|
.B ulimit
|
||||||
|
built-in command, such as
|
||||||
|
.BR "ulimit -t unlimited 2>/dev/null" ,
|
||||||
|
is a reliable way to make a subshell fork if it hasn't already.
|
||||||
|
.TP
|
||||||
|
.B .sh.ppid
|
||||||
|
Set to the process ID of the parent of the current shell process.
|
||||||
|
Unlike
|
||||||
|
.BR $PPID ,
|
||||||
|
this is updated in a subshell when it forks into a new process.
|
||||||
|
The same note as for
|
||||||
.B .sh.pid
|
.B .sh.pid
|
||||||
retains its previous value.
|
applies.
|
||||||
.TP
|
.TP
|
||||||
.B .sh.value
|
.B .sh.value
|
||||||
Set to the value of the variable at the time that the
|
Set to the value of the variable at the time that the
|
||||||
|
@ -1864,7 +1932,11 @@ built-in command.
|
||||||
.TP
|
.TP
|
||||||
.B
|
.B
|
||||||
.SM PPID
|
.SM PPID
|
||||||
The process ID of the parent of the shell.
|
The process ID of the parent of the main shell process.
|
||||||
|
Note that this value will not change in a subshell,
|
||||||
|
even if the subshell runs in a different process.
|
||||||
|
See also
|
||||||
|
.BR .sh.ppid .
|
||||||
.TP
|
.TP
|
||||||
.B
|
.B
|
||||||
.SM PWD
|
.SM PWD
|
||||||
|
|
|
@ -1923,6 +1923,7 @@ static Init_t *nv_init(void)
|
||||||
#endif /* _hdr_locale */
|
#endif /* _hdr_locale */
|
||||||
(PPIDNOD)->nvalue.pidp = (&sh.ppid);
|
(PPIDNOD)->nvalue.pidp = (&sh.ppid);
|
||||||
(SH_PIDNOD)->nvalue.pidp = (&sh.current_pid);
|
(SH_PIDNOD)->nvalue.pidp = (&sh.current_pid);
|
||||||
|
(SH_PPIDNOD)->nvalue.pidp = (&sh.current_ppid);
|
||||||
(SH_SUBSHELLNOD)->nvalue.ip = (&sh.realsubshell);
|
(SH_SUBSHELLNOD)->nvalue.ip = (&sh.realsubshell);
|
||||||
(TMOUTNOD)->nvalue.lp = (&sh.st.tmout);
|
(TMOUTNOD)->nvalue.lp = (&sh.st.tmout);
|
||||||
(MCHKNOD)->nvalue.lp = (&sh_mailchk);
|
(MCHKNOD)->nvalue.lp = (&sh_mailchk);
|
||||||
|
|
|
@ -1007,7 +1007,7 @@ set -- $(
|
||||||
[[ -n $varname && $varname != '.sh' ]] && print -r -- "$varname"
|
[[ -n $varname && $varname != '.sh' ]] && print -r -- "$varname"
|
||||||
done
|
done
|
||||||
)
|
)
|
||||||
(($# >= 64)) || err_exit "could not read shtab_variables[]; adjust test script ($# items read)"
|
(($# >= 65)) || err_exit "could not read shtab_variables[]; adjust test script ($# items read)"
|
||||||
|
|
||||||
# ... unset
|
# ... unset
|
||||||
$SHELL -c '
|
$SHELL -c '
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue