Sure, you can implement your own system
function. Here's one from man7:
int
system(const char *command)
{
sigset_t blockMask, origMask;
struct sigaction saIgnore, saOrigQuit, saOrigInt, saDefault;
pid_t childPid;
int status, savedErrno;
if (command == NULL) /* Is a shell available? */
return system(":") == 0;
/* The parent process (the caller of system()) blocks SIGCHLD
and ignore SIGINT and SIGQUIT while the child is executing.
We must change the signal settings prior to forking, to avoid
possible race conditions. This means that we must undo the
effects of the following in the child after fork(). */
sigemptyset(&blockMask); /* Block SIGCHLD */
sigaddset(&blockMask, SIGCHLD);
sigprocmask(SIG_BLOCK, &blockMask, &origMask);
saIgnore.sa_handler = SIG_IGN; /* Ignore SIGINT and SIGQUIT */
saIgnore.sa_flags = 0;
sigemptyset(&saIgnore.sa_mask);
sigaction(SIGINT, &saIgnore, &saOrigInt);
sigaction(SIGQUIT, &saIgnore, &saOrigQuit);
switch (childPid = fork()) {
case -1: /* fork() failed */
status = -1;
break; /* Carry on to reset signal attributes */
case 0: /* Child: exec command */
/* We ignore possible error returns because the only specified error
is for a failed exec(), and because errors in these calls can't
affect the caller of system() (which is a separate process) */
saDefault.sa_handler = SIG_DFL;
saDefault.sa_flags = 0;
sigemptyset(&saDefault.sa_mask);
if (saOrigInt.sa_handler != SIG_IGN)
sigaction(SIGINT, &saDefault, NULL);
if (saOrigQuit.sa_handler != SIG_IGN)
sigaction(SIGQUIT, &saDefault, NULL);
sigprocmask(SIG_SETMASK, &origMask, NULL);
execl("/bin/sh", "sh", "-c", command, (char *) NULL);
_exit(127); /* We could not exec the shell */
default: /* Parent: wait for our child to terminate */
/* We must use waitpid() for this task; using wait() could inadvertently
collect the status of one of the caller's other children */
while (waitpid(childPid, &status, 0) == -1) {
if (errno != EINTR) { /* Error other than EINTR */
status = -1;
break; /* So exit loop */
}
}
break;
}
/* Unblock SIGCHLD, restore dispositions of SIGINT and SIGQUIT */
savedErrno = errno; /* The following may change 'errno' */
sigprocmask(SIG_SETMASK, &origMask, NULL);
sigaction(SIGINT, &saOrigInt, NULL);
sigaction(SIGQUIT, &saOrigQuit, NULL);
errno = savedErrno;
return status;
}
Just don't #include <stdlib.h>
or you will have conflicts.