Is there a POSIX way of setting zeroth argument of a target application?

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?

Asked By: phk

||

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
Answered By: Stéphane Chazelas

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"

Answered By: JdeBP
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.