1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
/****************************************************************
* *
* Copyright (c) 2013-2018 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_unistd.h"
#include "gtm_stdlib.h"
#include "gtm_signal.h"
#include "gtm_string.h"
#include <sys/wait.h>
#include <errno.h>
#include "have_crit.h"
#include "fork_init.h"
#include "eintr_wrappers.h"
#define RESTOREMASK(RC) \
{ \
sigaction(SIGINT, &old_intrpt, NULL); \
sigaction(SIGQUIT, &old_quit, NULL); \
SIGPROCMASK(SIG_SETMASK, &savemask, NULL, RC); \
}
error_def(ERR_INVSTRLEN);
int gtm_system(const char *cmdline)
{
return gtm_system_internal(NULL, NULL, NULL, cmdline);
}
int gtm_system_internal(const char *sh, const char *opt, const char *rtn, const char *cmdline)
{
struct sigaction ignore, old_intrpt, old_quit;
sigset_t mask, savemask;
pid_t pid;
int stat; /* child exit status */
int rc, ret; /* return value from waitpid */
int len, shlen;
intrpt_state_t prev_intrpt_state;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
DEFER_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM, prev_intrpt_state);
sigemptyset(&ignore.sa_mask);
ignore.sa_handler = SIG_IGN;
ignore.sa_flags = 0;
if (sigaction(SIGINT, &ignore, &old_intrpt))
{
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM, prev_intrpt_state);
return -1;
}
if (sigaction(SIGQUIT, &ignore, &old_quit))
{
sigaction(SIGINT, &old_intrpt, NULL);
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM, prev_intrpt_state);
return -1;
}
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
SIGPROCMASK(SIG_BLOCK, &mask, &savemask, rc);
if (rc)
{
sigaction(SIGINT, &old_intrpt, NULL);
sigaction(SIGQUIT, &old_quit, NULL);
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM, prev_intrpt_state);
return -1;
}
/* Shell and command options */
if (NULL == opt)
opt = "-c";
if (NULL == sh)
sh = GETENV("SHELL");
sh = (NULL == sh) || ('\0' == *sh) ? "/bin/sh" : sh;
/* Below FORK is not used as interrupts are already disabled at the
* beginning of this function
*/
pid = fork(); /* BYPASSOK */
if (0 > pid)
{
RESTOREMASK(rc);
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM, prev_intrpt_state);
return -1;
}
else if (0 == pid)
{
RESTOREMASK(rc);
assert('\0' != *cmdline);
if (NULL == rtn)
execl(sh, sh, opt, cmdline, NULL);
else
execl(sh, sh, opt, rtn, cmdline, NULL);
UNDERSCORE_EXIT(127);
} else
{
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM, prev_intrpt_state);
WAITPID(pid, &stat, 0, ret);
if ((-1 == ret) && (EINTR != errno))
stat = -1;
RESTOREMASK(rc);
return stat;
}
}
|