In bash you can use exec -a and in zsh you can alternatively also set ARGV0 to execute a program with a certain zeroth argument but is there also a POSIX way of doing so?
As suggested in this one comment you could create a (temporary) symbolic link to achieve this but this way I couldn’t set the new zeroth argument value to truly any arbitrary value, e.g. the command with a certain absolute path. So is there any other solution?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
No, there’s no POSIX way, other than compiling a C program that does it. As a quick and dirty one:
$ echo 'int main(int c,char*v[]){
execvp(v[1],&v[2]);perror(v[1]);return 127;}'>r.c && make r
$ ./r ps zzz -f
UID PID PPID C STIME TTY TIME CMD
chazelas 7412 7411 0 10:44 pts/4 00:00:00 /bin/zsh
chazelas 21187 7412 0 22:33 pts/4 00:00:00 zzz -f
exec -a is supported by ksh93, bash, zsh, busybox ash (since version 1.27.0), yash, mksh (since version r50e), the Schily Bourne Shell (since August 2015) so is the most widespread among shells.
Probably the most portable would be to resort to perl which is more likely to be available than a C compiler.
$ perl -e 'exec {shift} @ARGV' ps zzz -f
UID PID PPID C STIME TTY TIME CMD
chazelas 7554 7411 0 10:58 pts/12 00:00:00 /bin/zsh
chazelas 7630 7554 0 11:02 pts/12 00:00:00 zzz -f
Method 2
For completeness, here are some C and C++ programs for doing this that people have already compiled.
Going by the commentary that you point to, your apparent motivation for asking for “a POSIX way” of doing this is to know how one can achieve this same end with shells such as the Debian Almquist shell, the MirBSD Korn shell (before version R50e), the Debian POSIX-Compliant Ordinary shell, and other shells that do not have extensions for setting the 0th argument as the Bourne Again and Z shells have. (The ’93 Korn shell, and the MirBSD Korn shell from version R50e onwards, support an -a option to their built-in exec commands.)
execline
Laurent Bercot’s execline comes with an exec command. So to duplicate M. Chazelas’ example one would have an execline script such as
#!/command/execlineb -P exec -a zzz ps -f
Bercot’s exec is an ordinary external command, of course. So one could run it from within a Debian Almquist Shell script. To overlay the current shell program one would use the shell’s exec to overlay with Bercot exec, which in turn would set the 0th argument and overlay with the target program:
exec /command/exec -a "$argv0" printer.sh
nosh
The nosh toolset includes an exec command. To duplicate M. Chazelas’ example one would have a nosh script such as
#!/bin/nosh exec -a zzz ps -f
Although it is a nosh built-in, this exec is also accessible as an ordinary external command. So one could run it from within a Debian Almquist Shell script. To overlay the current shell program one would use the shell’s exec to overlay with the nosh toolset’s exec, which in turn would set the 0th argument and overlay with the target program:
exec /usr/local/bin/exec -a "$argv0" printer.sh
perp
Wayne Marshall’s perp includes a runargv0 command. This is an ordinary external command. So one could run it from within a Debian Almquist Shell script. To overlay the current shell program one would use the shell’s exec to overlay with the perp toolset’s runargv0, which in turn would set the 0th argument and overlay with the target program:
exec runargv0 printer.sh "$argv0"
runit
Gerrit Pape’s runit includes a chpst command. This is an ordinary external command. So one could run it from within a Debian Almquist Shell script. To overlay the current shell program one would use the shell’s exec to overlay with runit’s chpst, which in turn would set the 0th argument and overlay with the target program:
exec chpst -b "$argv0" printer.sh
ucspi-tcp
Daniel J. Bernstein’s ucspi-tcp includes an argv0 command. (argv0 is also available in djbwares.) This is an ordinary external command. So one could run it from within a Debian Almquist Shell script. To overlay the current shell program one would use the shell’s exec to overlay with ucspi-tcp’s argv0, which in turn would set the 0th argument and overlay with the target program:
exec argv0 printer.sh "$argv0"
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0