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