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 the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19 /*
20 * This code is a simplified version of do_system() from glibc-2.9.
21 * Its primary use is to be called by the wrapper, execwrappers.cpp:system().
22 * This way, calls to system() go to our do_system(), which inherits our
23 * wrappers around fork/exec.
24 * Without this, any call to system() would go directly to glibc, where
25 * it would pick up the _unwrapped_ versions of fork/exec already defined
26 * in glibc. If you really want an unwrapped version of glibc's system(),
27 * then call execwrappers.cpp:_real_system().
28 */
29
30 #include <errno.h>
31 #include <signal.h>
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37
38 #define SHELL_PATH "/bin/sh" /* Path of the shell. */
39 #define SHELL_NAME "sh" /* Name to give it. */
40
41
42 #ifdef _LIBC_REENTRANT
43 static struct sigaction intr, quit;
44 static int sa_refcntr;
45 __libc_lock_define_initialized (static, lock);
46
47 # define DO_LOCK() __libc_lock_lock (lock)
48 # define DO_UNLOCK() __libc_lock_unlock (lock)
49 # define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
50 # define ADD_REF() sa_refcntr++
51 # define SUB_REF() --sa_refcntr
52 #else
53 # define DO_LOCK()
54 # define DO_UNLOCK()
55 # define INIT_LOCK()
56 # define ADD_REF() 0
57 # define SUB_REF() 0
58 #endif
59
60
61 /* Execute LINE as a shell command, returning its status. */
62 int do_system (const char *line)
63 {
64 int status, save;
65 pid_t pid;
|
Event var_decl: |
Declaring variable "sa" without initializer. |
| Also see events: |
[uninit_use_in_call] |
66 struct sigaction sa;
67 #ifndef _LIBC_REENTRANT
68 struct sigaction intr, quit;
69 #endif
70 sigset_t omask;
71
72 sa.sa_handler = SIG_IGN;
73 sa.sa_flags = 0;
74 sigemptyset (&sa.sa_mask);
75
76 DO_LOCK ();
|
At conditional (1): "true": Taking true branch.
|
77 if (ADD_REF () == 0)
78 {
|
Event uninit_use_in_call: |
Using uninitialized value "sa": field "sa".sa_restorer is uninitialized when calling "sigaction". |
| Also see events: |
[var_decl] |
79 if (sigaction (SIGINT, &sa, &intr) < 0)
80 {
81 SUB_REF ();
82 goto out;
83 }
84 if (sigaction (SIGQUIT, &sa, &quit) < 0)
85 {
86 save = errno;
87 SUB_REF ();
88 goto out_restore_sigint;
89 }
90 }
91 DO_UNLOCK ();
92
93 /* We reuse the bitmap in the 'sa' structure. */
94 sigaddset (&sa.sa_mask, SIGCHLD);
95 save = errno;
96 if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
97 {
98 #ifndef _LIBC
99 if (errno == ENOSYS)
100 errno = save;
101 else
102 #endif
103 {
104 DO_LOCK ();
105 if (SUB_REF () == 0)
106 {
107 save = errno;
108 (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
109 out_restore_sigint:
110 (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
111 errno = save;
112 //set_errno (save);
113 }
114 out:
115 DO_UNLOCK ();
116 return -1;
117 }
118 }
119
120 #ifdef CLEANUP_HANDLER
121 CLEANUP_HANDLER;
122 #endif
123
124 #ifdef FORK
125 pid = fork ();
126 #else
127 pid = fork ();
128 #endif
129 if (pid == (pid_t) 0)
130 {
131 /* Child side. */
132 const char *new_argv[4];
133 new_argv[0] = SHELL_NAME;
134 new_argv[1] = "-c";
135 new_argv[2] = line;
136 new_argv[3] = NULL;
137
138 /* Restore the signals. */
139 (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
140 (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
141 (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
142 INIT_LOCK ();
143
144 /* Exec the shell. */
145 (void) execve (SHELL_PATH, (char *const *) new_argv, __environ);
146 _exit (127);
147 }
148 else if (pid < (pid_t) 0)
149 /* The fork failed. */
150 status = -1;
151 else
152 /* Parent side. */
153 {
154 /* Note the system() is a cancellation point. But since we call
155 waitpid() which itself is a cancellation point we do not
156 have to do anything here. */
157 do {
158 if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
159 status = -1;
160 }
161 while (WIFEXITED(status) == 0);
162 }
163
164 #ifdef CLEANUP_HANDLER
165 CLEANUP_RESET;
166 #endif
167
168 save = errno;
169 DO_LOCK ();
170 if ((SUB_REF () == 0
171 && (sigaction (SIGINT, &intr, (struct sigaction *) NULL)
172 | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
173 || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
174 {
175 #ifndef _LIBC
176 /* glibc cannot be used on systems without waitpid. */
177 if (errno == ENOSYS)
178 errno = save;
179 else
180 #endif
181 status = -1;
182 }
183 DO_UNLOCK ();
184
185 return status;
186 }
187