1

In the following C program:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int     main(void){
        char *shell = getenv("SHELL");
        execl(shell, NULL, NULL);
        perror("execl() failed");
}

When I run the above I find myself inside a new shell. When I type exit the new shell exits and I find myself back in my old shell.

Shouldn't execl() replace the current shell with a new shell (and not spawn a new shell inside the old shell)?

(Linux 4.16)

  • Not related to the question, but it should be execl(shell, shell, (char *)NULL); – Barmar Jul 9 '18 at 18:22
5

Shouldn't execl() replace the current shell with a new shell (and not spawn a new shell inside the old shell)?

It replaces the current process, which is the process running your program, not the shell.

When you start your program, the process tree looks like

old shell → your program

When your program calls execl(), that tree becomes

old shell → new shell

so when you exit the shell, you return to the old shell.

If you want to replace the old shell, you need to tell the old shell to replace itself with your new program:

exec ./yourprogram

Then your program will replace itself with the new shell, and you’ll have replaced the old shell with the new one (with an extra step involving your program).

  • got it thanks! Is there any way via C to replace the grand-parent process so-to-speak? – bliako Jul 9 '18 at 13:07
  • 1
    There’s no reliable way: one process isn’t supposed to be able to modify another (including replacing it). You can use interfaces designed for debuggers (ptrace etc.) to cause another process to call a function such as execl() (in the same way you can by connecting gdb to a running process). – Stephen Kitt Jul 9 '18 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.