Since you mention it's fine with you, I feel obliged to introduce bash's equivalent...
ctypes.sh, a foreign function interface for bash
It's a shared object plugin for bash that is loaded with bash's enable -f
mechanism:
enable [-a] [-dnps] [-f filename] [name ...]
The -f
option means to load the new builtin command name from shared object filename, on systems that support dynamic loading.
and implemented in C language. It works at least on most Linux distributions and on FreeBSD.
You'll have to compile and install it first. The main feature is the ability to use almost any library call or system call from the shell. Though calls requiring structures might become way more complex to use when the builtin struct
fails to reconstruct them automatically.
Example typed in current bash shell, on amd64 (x86_64) architecture and Linux kernel 5.6 (in some cases constants depend on architecture and (more uncommonly) kernel version):
$ source /usr/local/bin/ctypes.sh
$ dlcall -r int prctl int:36 ulong:1 ulong:0 ulong:0 ulong:0
int:0
$ echo $DLRETVAL # you can't use $() above to get the result since that would be a subshell
int:0
$ echo $$; bash -c 'echo $$; sleep 99 & echo $!; disown -a'
14767
16761
16762
$ pstree -p $$
bash(14767)─┬─pstree(16778)
└─sleep(16762)
The sleep
process having lost its parent process (bash
pid 16761), has been inherited by the current shell instead of the init process: it worked.
Note that PR_SET_CHILD_SUBREAPER
had to be replaced by its value (and type) as found in /usr/include/linux/prctl.h
on this system:
#define PR_SET_CHILD_SUBREAPER 36
You'll have to check the documentation to use it properly.
Also, the shell's standard wait
might not work as expected for this: the shell didn't spawn that sleep
command so the wait
command won't do anything. You might have to invest into dlcalling wait()
, waitpid()
& co. This could be difficult, because bash itself alters settings and uses wait()
-like calls each time it runs a command, so some unforeseen interactions to handle those inherited processes are likely.
This would achieve the same result as before (there must be some options to get it less verbose):
$ gdb -ex 'call (int)prctl((int)36,(long)1,(long)0,(long)0,(long)0)' -ex detach -ex quit -p $$
gdb --pid $$ -ex 'call prctl(36, 1, 0, 0, 0, 0)' -ex 'quit $1'
? I'll test it and report, I actually like it more as it doesn't involve installing anything (which could be tricky in the environment I work in). – Giuseppe Musumeci May 27 '20 at 19:01