ReactOS 0.4.16-dev-340-g0540c21
_system.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/sdk/crt/process/_system.c
5 * PURPOSE: Excutes a shell command
6 * PROGRAMER: Ariadne
7 * Katayama Hirofumi MZ
8 * UPDATE HISTORY:
9 * 04/03/99: Created
10 */
11
12#include <precomp.h>
13#include <stdlib.h>
14#include <string.h>
15#include <process.h>
16
17/*
18 * @implemented
19 */
20int system(const char *command)
21{
22 char *szCmdLine = NULL;
23 char *szComSpec = NULL;
24 PROCESS_INFORMATION ProcessInformation;
25 STARTUPINFOA StartupInfo;
27 int exit_code;
28 char cmd_exe[MAX_PATH];
29
30 szComSpec = getenv("COMSPEC");
31
32// system should return 0 if command is null and the shell is found
33
34 if (command == NULL) {
35 return (szComSpec == NULL) ? 0 : 1;
36 }
37
38 if (!szComSpec || GetFileAttributesA(szComSpec) == INVALID_FILE_ATTRIBUTES)
39 {
40 GetSystemDirectoryA(cmd_exe, _countof(cmd_exe));
41 strcat(cmd_exe, "\\cmd.exe");
42 szComSpec = cmd_exe;
43 }
44
45 szCmdLine = malloc(1 + strlen(szComSpec) + 5 + strlen(command) + 1);
46 if (szCmdLine == NULL)
47 {
49 return -1;
50 }
51
52 strcpy(szCmdLine, "\"");
53 strcat(szCmdLine, szComSpec);
54 strcat(szCmdLine, "\" /C ");
55 strcat(szCmdLine, command);
56
57//command file has invalid format ENOEXEC
58
59 memset(&StartupInfo, 0, sizeof(StartupInfo));
60 StartupInfo.cb = sizeof(StartupInfo);
61 StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
62 StartupInfo.wShowWindow = SW_SHOWDEFAULT;
63
64// In order to disable Ctrl+C, the process is created with CREATE_NEW_PROCESS_GROUP.
65// Thus, SetConsoleCtrlHandler(NULL, TRUE) is made on behalf of the new process.
66
67//SIGCHILD should be blocked as well
68
69 result = CreateProcessA(szComSpec,
70 szCmdLine,
71 NULL,
72 NULL,
73 TRUE,
75 NULL,
76 NULL,
77 &StartupInfo,
78 &ProcessInformation);
79 free(szCmdLine);
80
81 if (result == FALSE)
82 {
84 return -1;
85 }
86
87 CloseHandle(ProcessInformation.hThread);
88
89 /* Wait for the process to exit */
90 _cwait(&exit_code, (intptr_t)ProcessInformation.hProcess, 0);
91
92 CloseHandle(ProcessInformation.hProcess);
93
94 _set_errno(0);
95 return exit_code;
96}
97
98int CDECL _wsystem(const wchar_t *cmd)
99{
100 wchar_t *cmdline = NULL;
101 wchar_t *comspec = NULL;
102 PROCESS_INFORMATION process_info;
103 STARTUPINFOW startup_info;
104 BOOL result;
105 int exit_code;
106 wchar_t cmd_exe[MAX_PATH];
107
108 comspec = _wgetenv(L"COMSPEC");
109
110 /* _wsystem should return 0 if cmd is null and the shell is found */
111 if (cmd == NULL)
112 {
113 return (comspec == NULL) ? 0 : 1;
114 }
115
116 if (comspec == NULL || GetFileAttributesW(comspec) == INVALID_FILE_ATTRIBUTES)
117 {
118 GetSystemDirectoryW(cmd_exe, _countof(cmd_exe));
119 wcscat(cmd_exe, L"\\cmd.exe");
120 comspec = cmd_exe;
121 }
122
123 cmdline = malloc((1 + wcslen(comspec) + 5 + wcslen(cmd) + 1) * sizeof(wchar_t));
124 if (cmdline == NULL)
125 {
127 return -1;
128 }
129
130 wcscpy(cmdline, L"\"");
131 wcscat(cmdline, comspec);
132 wcscat(cmdline, L"\" /C ");
134
135 /* command file has invalid format ENOEXEC */
136
137 memset(&startup_info, 0, sizeof(startup_info));
138 startup_info.cb = sizeof(startup_info);
139 startup_info.dwFlags = STARTF_USESHOWWINDOW;
140 startup_info.wShowWindow = SW_SHOWDEFAULT;
141
142 /* In order to disable Ctrl+C, the process is created with CREATE_NEW_PROCESS_GROUP.
143 Thus, SetConsoleCtrlHandler(NULL, TRUE) is made on behalf of the new process. */
144
145 /* SIGCHILD should be blocked as well */
146
147 /* Create the process to execute the command */
148 result = CreateProcessW(comspec,
149 cmdline,
150 NULL,
151 NULL,
152 TRUE,
154 NULL,
155 NULL,
156 &startup_info,
157 &process_info);
158 free(cmdline);
159
160 if (!result)
161 {
163 return -1;
164 }
165
166 CloseHandle(process_info.hThread);
167
168 /* Wait for the process to exit */
169 _cwait(&exit_code, (intptr_t)process_info.hProcess, 0);
170
171 CloseHandle(process_info.hProcess);
172
173 _set_errno(0);
174 return exit_code;
175}
int system(const char *command)
Definition: _system.c:20
int CDECL _wsystem(const wchar_t *cmd)
Definition: _system.c:98
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define ENOMEM
Definition: acclib.h:84
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CDECL
Definition: compat.h:29
#define CloseHandle
Definition: compat.h:739
#define MAX_PATH
Definition: compat.h:34
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:636
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
UINT WINAPI GetSystemDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2283
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4598
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4747
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint64EXT * result
Definition: glext.h:11304
_Check_return_ _CRTIMP wchar_t *__cdecl _wgetenv(_In_z_ const wchar_t *_VarName)
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
static UINT exit_code
Definition: process.c:78
#define L(x)
Definition: ntvdm.h:50
void _dosmaperr(unsigned long oserrcode)
Definition: errno.c:79
errno_t __cdecl _set_errno(_In_ int _Value)
_CRTIMP intptr_t __cdecl _cwait(_Out_opt_ int *_TermStat, _In_ intptr_t _ProcHandle, _In_ int _Action)
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define memset(x, y, z)
Definition: compat.h:39
#define _countof(array)
Definition: sndvol32.h:70
TCHAR * cmdline
Definition: stretchblt.cpp:32
DWORD dwFlags
Definition: winbase.h:867
DWORD cb
Definition: winbase.h:856
WORD wShowWindow
Definition: winbase.h:868
DWORD cb
Definition: winbase.h:877
DWORD dwFlags
Definition: winbase.h:888
WORD wShowWindow
Definition: winbase.h:889
Definition: ftp_var.h:139
int intptr_t
Definition: vcruntime.h:134
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define STARTF_USESHOWWINDOW
Definition: winbase.h:517
#define CREATE_NEW_PROCESS_GROUP
Definition: winbase.h:188
#define SW_SHOWDEFAULT
Definition: winuser.h:783