1

I am running nmap from a C program using execl:

execl("/bin/sh","sh","-c","sudo nmap -sS -A 192.168.0.1/24",NULL);

I have HTOP running in in another shell window and I see that my execl starts there PIDs:

2339 for command "nmap -sS .."
2335 for command "sudo nmap -sS .."
2334 for command "sh .."

The child PID is 2334. Nmap takes a long time to finish and if I want to kill all three processes I issue kill 2339 from the shell. All 2339,2335 and 2334 then vanish from HTOP monitoring program.

What I would like to do is issue kill(2339, ...) within my C program and kill all like I can do from the shell. My problem is that how do I get the PID 2339? My childPID is in this example 2334.

1
  • 1
    Killing the shell you started, i.e. pid 2334, will in turn kill its children.
    – psusi
    Commented Jun 6, 2017 at 0:59

2 Answers 2

3

First, you can simplify your problem by cutting out one of the middle processes: there is no reason here for you to use sh -c to launch your process. In fact, it's potentially less secure, if your actual command line is dynamically constructed. Instead of:

execl("/bin/sh","sh","-c","sudo nmap -sS -A 192.168.0.1/24",NULL);

You should just do:

execlp("sudo", "sudo", "nmap", "-sS", "-A", "192.168.0.1/24", NULL);

Now you have just two processes: the sudo and the nmap itself. You know the process ID of the parent (sudo) but you don't know the process ID of the child (nmap). But it doesn't matter, because you can use a feature of sudo: kill the parent (with SIGTERM) and it will forward the signal along to the child for you.

Your last remaining problem isn't directly related to the question you're asking, but it's that anyway you probably don't have permission to kill either of these processes anyway! Since sudo is involved, which has as its purpose to elevate its privilege, you probably don't have permission to send it or its child signals in the first place.

2
  • 1
    Your answers are so Feynmanesque that while reading them it appears all so very clear... but afterwards, i dunno how the reasoning went :-\ A true mark of a master. +1
    – user218374
    Commented Jun 5, 2017 at 22:31
  • I use the execl & shell for ease of use as it works with other command with macro expansion, for example "ls -l somestr*". For most case I can just most shell commands as the fourth parameter and do not have to parse it. My question about the pid 2339 remains. Is the any way to get that so I could try kill it. My main program runs with sudo elevation. Commented Jun 6, 2017 at 6:25
1

One method would be to sudo kill the child pid from the parent process, assuming sudoers grants that.

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

void sudokill(pid_t tokill);

int main(void)
{
    pid_t pid;

    pid = fork();
    switch (pid) {
    case -1:
        err(1, "fork() failed");
    case 0:
        execlp("sudo", "sudo", "sleep", "999", (char *) NULL);
        err(1, "execlp() failed");
    default:
        sleep(7);
        sudokill(pid);
    }
    exit(EXIT_SUCCESS);
}

void sudokill(pid_t tokill)
{
    char *killstr;
    int status;
    pid_t pid;

    if (asprintf(&killstr, "%d", tokill) < 0)
        err(1, "asprintf() failed");

    pid = fork();
    switch (pid) {
    case -1:
        err(1, "fork() failed");
    case 0:
        execlp("sudo", "sudo", "kill", killstr, (char *) NULL);
        err(1, "execlp() failed");
    default:
        wait(&status);
    }

    free(killstr);
}
1
  • Unfortunately this does not achieve my goal. In my example the pid of the child process is known (2334), but killing it won't kill the other two processes. Only by killing 2339 (which is unkown) in my example all three processes are removed Commented Jun 6, 2017 at 6:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .