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 */ 20 int system(const char *command) 21 { 22 char *szCmdLine = NULL; 23 char *szComSpec = NULL; 24 PROCESS_INFORMATION ProcessInformation; 25 STARTUPINFOA StartupInfo; 26 BOOL result; 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 { 48 _set_errno(ENOMEM); 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, 74 CREATE_NEW_PROCESS_GROUP, 75 NULL, 76 NULL, 77 &StartupInfo, 78 &ProcessInformation); 79 free(szCmdLine); 80 81 if (result == FALSE) 82 { 83 _dosmaperr(GetLastError()); 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 98 int 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 { 126 _set_errno(ENOMEM); 127 return -1; 128 } 129 130 wcscpy(cmdline, L"\""); 131 wcscat(cmdline, comspec); 132 wcscat(cmdline, L"\" /C "); 133 wcscat(cmdline, cmd); 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, 153 CREATE_NEW_PROCESS_GROUP, 154 NULL, 155 NULL, 156 &startup_info, 157 &process_info); 158 free(cmdline); 159 160 if (!result) 161 { 162 _dosmaperr(GetLastError()); 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 } 176