Question about system command in C

The man system says

During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.

What does this mean?
And if i am making a function that does what system does how do i write this signal stuff?

It means that SIGCHLD signals won't be handled during the time system() is still being processed.

You do that with sigprocmask, which is used to view or modify the set of signals the process is currently blocking or whatever. Change the signals at the beginning and then, right before you return, change them back. See man sigprocmask.

I'm still not understanding how to ignore SIGINT and SIGQUIT in the parent and not the child.
If i press ctrl-c while the child process is still going on, its supposed to end the child process, and create a zombie process (parent)?

Set the parent to ignore them, fork(), then change it back in the child.

I'm not completely sure. what actualy ends up happening?

int system_new(const char *comm) {
    int fd[2], status, pid; 
    if (pipe(fd) < 0) { 
        perror("pipe failed"); 
        return ((int) NULL);
    }
    if ((pid = fork()) == 0) { 
        close(fd[0]); close(fd[1]);
        execl("/bin/sh", "/bin/sh", "-c", comm, NULL); 
        perror("couldn't execl"); exit(127); 
    }
    else if (pid > 0) { 
        close(fd[0]); close(fd[1]); 
        wait(&status); 
    }
    else { 
        close(fd[0]); close(fd[1]);
        perror("fork failed"); exit(-1); 
    }
    return WEXITSTATUS(status); 
}

You're not actually using the pipe here, so you can cut all the bits that create and close the pipe...

To block SIGCHLD in the parent do i need
sigset_t new;
sigemptyset (&new);
sigaddset(&new, SIGCHLD);
sigprocmask(SIG_BLOCK, &new, NULL);
?

That'd work, yes.

I'd keep a copy of the old signals just to make it easy to undo.

sigset_t new, old;
sigemptyset (&new);
sigaddset(&new, SIGCHLD);
sigprocmask(SIG_BLOCK, &new, &old);

...

// in child, undo by setting to the old mask
sigprocmask(SIG_SETMASK&old, NULL);

so like
this will block SIGCHLD in parent, so if one were to press ctrl-c when child were running, what would happen?

minor typo:

sigprocmask(SIG_SETMASK,&old, NULL);

I think that means any other children which quit while system() was waiting for its own wouldn't interrupt it. Once you unblock the signals again they should come through.

You forgot to return the signals to the way they were again before you return. Do sigprocmask(SIG_SETMASK,&old, NULL); again right before return().

ok so if SIG_BLOCK blocks the signal, is there such thing as SIG_IGNORE ?
edit: i think its SIG_IGN

so to ignore SIGINT and SIGQUIT, I need something like
sigprocmask(SIG_IGN, &new, &old);

No. sigprocmask only blocks or unblocks signals. See man sigprocmask.

SIG_IGN is used by sigaction(). I think you use it like

struct sigaction act;

act.sa_handler=SIG_IGN;
act.sa_flags=0;

sigaction(SIGINT, &act, NULL);

so i have to be using

sigset_t new, old;      
sigemptyset (&new);      
sigaddset(&new, SIGINT, SIGQUIT);  

sigaction(SIGINT, &new, %old);
sigaction(SIGQUIT, &new, %old);

No, sigaction has nothing to do with sigprocmask. See man sigprocmask and man sigaction. These manual pages will be very, very helpful to you.

I don't know what %old is supposed to do. That doesn't look like valid C.

I edited in an example while you were answering I think.

OK then i should be using

struct sigaction act1, act2; 
act1.sa_handler=SIG_IGN; act1.sa_flags=0;
act2.sa_handler=SIG_QUIT; act2.sa_flags=0;
sigaction(SIGINT, &act1, NULL);
sigaction(SIGQUIT, &act2, NULL);

Close.

act2.sa_handler=SIG_IGN; act2.sa_flags=0;

And actually, it just occurred to me that you should be putting back the old actions once you're done.

struct sigaction act1, oldact1;

act1.sa_handler=SIG_IGN; act1.sa_flags=0;
// Set a new action for SIGINT and save the old one for later
sigaction(SIGINT, &act1, &oldact1);

...

// Put it back after
sigaction(SIGINT, &oldact1, NULL);

I'm not sure if you should undo it in the child before exec or not.

ok so then its like
is it waitpid(pid, NULL, 0); or waitpid(&status, NULL, 0);

No. sigaction takes three parameters, not two, and you forgot to save the old structures.

You should also use waitpid(), not wait(), or else you might end up waiting for the wrong child.

i modified my previous post can u see if everything is ok

You should also put the sigprocmask/sigaction resets in the { perror("fork failed"); exit(-1); } section, otherwise you won't reset them when fork throws an error. Otherwise, it looks OK now. :b:

ok i re-modified the previous post

Looks very good now :b: