/* * Copyright (c) 2000, Amnon BARAK (amnon@cs.huji.ac.il). All rights reserved. * * Permission to use, copy and distribute this software is hereby granted * under the terms of version 2 or any later version of the GNU General Public * License, as published by the Free Software Foundation. * * THIS SOFTWARE IS PROVIDED IN ITS "AS IS" CONDITION, WITH NO WARRANTY * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED. */ /* Adapted to OpenMosix from Mosix and bugfixing by David Santo Orcero */ /* irbis@orcero.org http://www.orcero.org/irbis */ /* Mosix is (c) of prof. Amnon Barak http://www.mosix.org */ /* Original code is (c) of prof. Amnon Barak http://www.mosix.org */ /* OpenMosix is (c) of Moshe Bar http://www.openmosix.com */ /* Each respective trademark is of its own owner */ /* All rights reserved. */ /* This software is distributed under GPL 2 */ /* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTY IS ASSUMED. */ /* NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING */ /* FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED. IT CAN BURN */ /* YOUR HARD DISK, ERASE ALL YOUR DATA AND BROKE DOWN YOUR */ /* MICROWAVE OVEN. YOU ARE ADVISED. */ /* * Author(s): Ariel Eizenberg */ /* Based on glibc2.1.3 */ #include #include #include #include #include #include #include #define set_errno(Val) errno = (Val) #define SHELL_PATH "/bin/sh" /* Path of the shell. */ #define SHELL_NAME "sh" /* Name to give it. */ int system (const char *line) { int status, save; pid_t pid; struct sigaction sa, intr, quit; sigset_t block, omask; if (line == NULL) /* Check that we have a command processor available. It might not be available after a chroot(), for example. */ return system("exit 0") == 0; sa.sa_handler = SIG_IGN; sa.sa_flags = 0; sigemptyset (&sa.sa_mask); if (sigaction (SIGINT, &sa, &intr) < 0) return -1; if (sigaction (SIGQUIT, &sa, &quit) < 0) { save = errno; (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); set_errno(save); return -1; } sigemptyset (&block); sigaddset (&block, SIGCHLD); save = errno; if (sigprocmask (SIG_BLOCK, &block, &omask) < 0) { if (errno == ENOSYS) set_errno (save); else { save = errno; (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); set_errno (save); return -1; } } pid = fork ();/* use vfork instead of fork */ if (pid == (pid_t) 0) { /* Child side. */ const char *new_argv[4]; new_argv[0] = SHELL_NAME; new_argv[1] = "-c"; new_argv[2] = line; new_argv[3] = NULL; /* Restore the signals. */ (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL); /* Exec the shell. */ (void) execve (SHELL_PATH, (char * const *) new_argv, __environ); _exit (127); } else if (pid < (pid_t) 0) /* The fork failed. */ status = -1; else /* Parent side. */ { pid_t child; do { child = wait (&status); if (child <= -1 && errno != EINTR) { status = -1; break; } /* Note that pid cannot be <= -1 and therefore the loop continues when wait returned with EINTR. */ } while (child != pid); } save = errno; if ((sigaction (SIGINT, &intr, (struct sigaction *) NULL) | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL) | sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL)) != 0) { if (errno == ENOSYS) set_errno (save); else return -1; } return status; }