File: gtm_system.c

package info (click to toggle)
fis-gtm 7.1-006-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 32,908 kB
  • sloc: ansic: 344,906; asm: 5,184; csh: 4,859; sh: 2,000; awk: 294; makefile: 73; sed: 13
file content (114 lines) | stat: -rw-r--r-- 2,959 bytes parent folder | download | duplicates (5)
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;
	}
}