root/glibcsystem.cpp
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- do_system
1 /* Copyright (C) 1991-2000,2002,2003,2005,2007 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with DMTCP:dmtcp/src. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 /*
19 * This code is a simplified version of do_system() from glibc-2.9.
20 * Its primary use is to be called by the wrapper, execwrappers.cpp:system().
21 * This way, calls to system() go to our do_system(), which inherits our
22 * wrappers around fork/exec.
23 * Without this, any call to system() would go directly to glibc, where
24 * it would pick up the _unwrapped_ versions of fork/exec already defined
25 * in glibc. If you really want an unwrapped version of glibc's system(),
26 * then call execwrappers.cpp:_real_system().
27 */
28 #include <errno.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32
33 #define SHELL_PATH "/bin/sh" /* Path of the shell. */
34 #define SHELL_NAME "sh" /* Name to give it. */
35
36 /* Execute LINE as a shell command, returning its status. */
37 __attribute__ ((visibility ("hidden")))
38 int do_system (const char *line)
39 {
40 int status, save;
41 pid_t pid;
42 struct sigaction sa;
43 struct sigaction intr, quit;
44 sigset_t omask;
45
46 sa.sa_handler = SIG_IGN;
47 sa.sa_flags = 0;
48 sigemptyset (&sa.sa_mask);
49
50 if (sigaction (SIGINT, &sa, &intr) < 0) {
51 goto out;
52 }
53 if (sigaction (SIGQUIT, &sa, &quit) < 0) {
54 save = errno;
55 goto out_restore_sigint;
56 }
57
58 /* We reuse the bitmap in the 'sa' structure. */
59 sigaddset (&sa.sa_mask, SIGCHLD);
60 save = errno;
61 if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) {
62 if (errno == ENOSYS) {
63 errno = save;
64 } else {
65 save = errno;
66 (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
67 out_restore_sigint:
68 (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
69 errno = save;
70 //set_errno (save);
71 out:
72 return -1;
73 }
74 }
75
76 pid = fork ();
77 if (pid == (pid_t) 0) {
78 /* Child side. */
79 const char *new_argv[4];
80 new_argv[0] = SHELL_NAME;
81 new_argv[1] = "-c";
82 new_argv[2] = line;
83 new_argv[3] = NULL;
84
85 /* Restore the signals. */
86 (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
87 (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
88 (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
89
90 /* Exec the shell. */
91 (void) execve (SHELL_PATH, (char *const *) new_argv, __environ);
92 _exit (127);
93 } else if (pid < (pid_t) 0) {
94 /* The fork failed. */
95 status = -1;
96 } else {
97 /* Parent side. */
98 /* Note that system() is a cancellation point. But since we call
99 waitpid() which itself is a cancellation point we do not
100 have to do anything here. */
101 do {
102 if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
103 status = -1;
104 }
105 while (WIFEXITED(status) == 0);
106 }
107
108 save = errno;
109 if (((sigaction (SIGINT, &intr, (struct sigaction *) NULL)
110 | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
111 || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0) {
112 /* glibc cannot be used on systems without waitpid. */
113 if (errno == ENOSYS)
114 errno = save;
115 else
116 status = -1;
117 }
118
119 return status;
120 }
121