Back to index

glibc  2.9
system.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991-2000,2002,2003,2005,2007 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <errno.h>
00020 #include <signal.h>
00021 #include <stddef.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <sys/types.h>
00025 #include <sys/wait.h>
00026 #include <bits/libc-lock.h>
00027 #include <sysdep-cancel.h>
00028 
00029 
00030 #define       SHELL_PATH    "/bin/sh"     /* Path of the shell.  */
00031 #define       SHELL_NAME    "sh"          /* Name to give it.  */
00032 
00033 
00034 #ifdef _LIBC_REENTRANT
00035 static struct sigaction intr, quit;
00036 static int sa_refcntr;
00037 __libc_lock_define_initialized (static, lock);
00038 
00039 # define DO_LOCK() __libc_lock_lock (lock)
00040 # define DO_UNLOCK() __libc_lock_unlock (lock)
00041 # define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
00042 # define ADD_REF() sa_refcntr++
00043 # define SUB_REF() --sa_refcntr
00044 #else
00045 # define DO_LOCK()
00046 # define DO_UNLOCK()
00047 # define INIT_LOCK()
00048 # define ADD_REF() 0
00049 # define SUB_REF() 0
00050 #endif
00051 
00052 
00053 /* Execute LINE as a shell command, returning its status.  */
00054 static int
00055 do_system (const char *line)
00056 {
00057   int status, save;
00058   pid_t pid;
00059   struct sigaction sa;
00060 #ifndef _LIBC_REENTRANT
00061   struct sigaction intr, quit;
00062 #endif
00063   sigset_t omask;
00064 
00065   sa.sa_handler = SIG_IGN;
00066   sa.sa_flags = 0;
00067   __sigemptyset (&sa.sa_mask);
00068 
00069   DO_LOCK ();
00070   if (ADD_REF () == 0)
00071     {
00072       if (__sigaction (SIGINT, &sa, &intr) < 0)
00073        {
00074          SUB_REF ();
00075          goto out;
00076        }
00077       if (__sigaction (SIGQUIT, &sa, &quit) < 0)
00078        {
00079          save = errno;
00080          SUB_REF ();
00081          goto out_restore_sigint;
00082        }
00083     }
00084   DO_UNLOCK ();
00085 
00086   /* We reuse the bitmap in the 'sa' structure.  */
00087   __sigaddset (&sa.sa_mask, SIGCHLD);
00088   save = errno;
00089   if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
00090     {
00091 #ifndef _LIBC
00092       if (errno == ENOSYS)
00093        __set_errno (save);
00094       else
00095 #endif
00096        {
00097          DO_LOCK ();
00098          if (SUB_REF () == 0)
00099            {
00100              save = errno;
00101              (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
00102            out_restore_sigint:
00103              (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
00104              __set_errno (save);
00105            }
00106        out:
00107          DO_UNLOCK ();
00108          return -1;
00109        }
00110     }
00111 
00112 #ifdef CLEANUP_HANDLER
00113   CLEANUP_HANDLER;
00114 #endif
00115 
00116 #ifdef FORK
00117   pid = FORK ();
00118 #else
00119   pid = __fork ();
00120 #endif
00121   if (pid == (pid_t) 0)
00122     {
00123       /* Child side.  */
00124       const char *new_argv[4];
00125       new_argv[0] = SHELL_NAME;
00126       new_argv[1] = "-c";
00127       new_argv[2] = line;
00128       new_argv[3] = NULL;
00129 
00130       /* Restore the signals.  */
00131       (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
00132       (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
00133       (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
00134       INIT_LOCK ();
00135 
00136       /* Exec the shell.  */
00137       (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
00138       _exit (127);
00139     }
00140   else if (pid < (pid_t) 0)
00141     /* The fork failed.  */
00142     status = -1;
00143   else
00144     /* Parent side.  */
00145     {
00146       /* Note the system() is a cancellation point.  But since we call
00147         waitpid() which itself is a cancellation point we do not
00148         have to do anything here.  */
00149       if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
00150        status = -1;
00151     }
00152 
00153 #ifdef CLEANUP_HANDLER
00154   CLEANUP_RESET;
00155 #endif
00156 
00157   save = errno;
00158   DO_LOCK ();
00159   if ((SUB_REF () == 0
00160        && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL)
00161           | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
00162       || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
00163     {
00164 #ifndef _LIBC
00165       /* glibc cannot be used on systems without waitpid.  */
00166       if (errno == ENOSYS)
00167        __set_errno (save);
00168       else
00169 #endif
00170        status = -1;
00171     }
00172   DO_UNLOCK ();
00173 
00174   return status;
00175 }
00176 
00177 int
00178 __libc_system (const char *line)
00179 {
00180   if (line == NULL)
00181     /* Check that we have a command processor available.  It might
00182        not be available after a chroot(), for example.  */
00183     return do_system ("exit 0") == 0;
00184 
00185   if (SINGLE_THREAD_P)
00186     return do_system (line);
00187 
00188   int oldtype = LIBC_CANCEL_ASYNC ();
00189 
00190   int result = do_system (line);
00191 
00192   LIBC_CANCEL_RESET (oldtype);
00193 
00194   return result;
00195 }
00196 weak_alias (__libc_system, system)