/*****
* $Id: cmd_sh.c,v 1.2 2001/01/25 09:08:51 harbourn Exp $
* sh command for fatback
*****/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "interface_data.h"
#include "interface.h"
/*
* Execute a command in the outside environment
* similar to the system() function except with
* proper signal handeling.
*/
void cmd_sh(int argc, char *argv[])
{
pid_t pid;
int status;
struct sigaction ignore, saveintr, savequit;
sigset_t chldmask, savemask;
if (argc < 2) {
printf("Usage: sh [command]\n");
return;
}
/* move argc and argv past the initial "sh" */
argc--;
argv++;
/* This is basically and intellegent implementation of
* system() with signal handling */
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
ignore.sa_flags = 0;
if ((sigaction(SIGINT, &ignore, &saveintr) < 0) ||
(sigaction(SIGQUIT, &ignore, &saveintr))) {
printf("Error assigning sigaction\n");
return;
}
sigemptyset(&chldmask);
sigaddset(&chldmask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) {
printf("Error setting sigprocmask\n");
return;
}
if ((pid = fork()) == 0) {
/* child */
sigaction(SIGINT, &saveintr, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &savemask, NULL);
execvp(argv[0], &argv[0]);
exit(127); /* if an error occurred */
} else {
/* parent */
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
break;
}
/* now restore the previous actions and masks */
if ((sigaction(SIGINT, &saveintr, NULL) < 0) ||
(sigaction(SIGQUIT, &savequit, NULL) < 0) ||
(sigprocmask(SIG_SETMASK, &savemask, NULL) < 0))
printf("Warning: signal handling not fully restored after returning from process\n");
return;
}
syntax highlighted by Code2HTML, v. 0.9.1