migrate substitution keywords to SVN
[reactos.git] / reactos / lib / msvcrt / process / _system.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/msvcrt/process/system.c
6 * PURPOSE: Excutes a shell command
7 * PROGRAMER: Boudewijn Dekker
8 * UPDATE HISTORY:
9 * 04/03/99: Created
10 */
11
12 #include "precomp.h"
13 #include <msvcrt/stdlib.h>
14 #include <msvcrt/string.h>
15 #include <msvcrt/process.h>
16 #include <msvcrt/errno.h>
17 #include <msvcrt/internal/file.h>
18
19 /*
20 * @implemented
21 */
22 int system(const char *command)
23 {
24 char *szCmdLine = NULL;
25 char *szComSpec = NULL;
26
27 PROCESS_INFORMATION ProcessInformation;
28 STARTUPINFOA StartupInfo;
29 char *s;
30 BOOL result;
31
32 int nStatus;
33
34 szComSpec = getenv("COMSPEC");
35
36 // system should return 0 if command is null and the shell is found
37
38 if (command == NULL) {
39 if (szComSpec == NULL)
40 return 0;
41 else
42 return -1;
43 }
44
45 // should return 127 or 0 ( MS ) if the shell is not found
46 // __set_errno(ENOENT);
47
48 if (szComSpec == NULL)
49 {
50 szComSpec = strdup("cmd.exe");
51 if (szComSpec == NULL)
52 {
53 __set_errno(ENOMEM);
54 return -1;
55 }
56 }
57
58 s = max(strchr(szComSpec, '\\'), strchr(szComSpec, '/'));
59 if (s == NULL)
60 s = szComSpec;
61 else
62 s++;
63
64 szCmdLine = malloc(strlen(s) + 4 + strlen(command) + 1);
65 if (szCmdLine == NULL)
66 {
67 free (szComSpec);
68 __set_errno(ENOMEM);
69 return -1;
70 }
71
72 strcpy(szCmdLine, s);
73 s = strrchr(szCmdLine, '.');
74 if (s)
75 *s = 0;
76 strcat(szCmdLine, " /C ");
77 strcat(szCmdLine, command);
78
79 //command file has invalid format ENOEXEC
80
81 memset (&StartupInfo, 0, sizeof(StartupInfo));
82 StartupInfo.cb = sizeof(StartupInfo);
83 StartupInfo.lpReserved= NULL;
84 StartupInfo.dwFlags = 0;
85 StartupInfo.wShowWindow = SW_SHOWDEFAULT;
86 StartupInfo.lpReserved2 = NULL;
87 StartupInfo.cbReserved2 = 0;
88
89 // According to ansi standards the new process should ignore SIGINT and SIGQUIT
90 // In order to disable ctr-c the process is created with CREATE_NEW_PROCESS_GROUP,
91 // thus SetConsoleCtrlHandler(NULL,TRUE) is made on behalf of the new process.
92
93
94 //SIGCHILD should be blocked aswell
95
96 result = CreateProcessA(szComSpec,
97 szCmdLine,
98 NULL,
99 NULL,
100 TRUE,
101 0,
102 NULL,
103 NULL,
104 &StartupInfo,
105 &ProcessInformation);
106 free(szCmdLine);
107 free(szComSpec);
108
109 if (result == FALSE)
110 {
111 _dosmaperr(GetLastError());
112 return -1;
113 }
114
115 CloseHandle(ProcessInformation.hThread);
116
117 // system should wait untill the calling process is finished
118 _cwait(&nStatus,(int)ProcessInformation.hProcess,0);
119 CloseHandle(ProcessInformation.hProcess);
120
121 return nStatus;
122 }