3 * Copyright (C) 2004-2008, The Perl Foundation.
10 config\gen\platform\win32\exec.c
14 Functions for dealing with child processes and Execs.
29 Parrot_Run_OS_Command(Parrot_Interp interp, STRING *command)>
31 Spawn the subprocess specified in C<command>.
32 Waits for the process to complete, and then
33 returns the exit code in POSIX-compatibility mode.
40 Parrot_Run_OS_Command(Parrot_Interp interp
, STRING
*command
)
44 PROCESS_INFORMATION pi
;
46 char* cmd
= mem_sys_allocate(command
->strlen
+ 4);
47 char* shell
= Parrot_getenv("ComSpec", &free_it
);
48 char* cmdin
= string_to_cstring(interp
, command
);
52 string_cstring_free(cmdin
);
54 memset(&si
, 0, sizeof (si
));
56 memset(&pi
, 0, sizeof (pi
));
58 /* Start the child process. */
59 if (!CreateProcess(shell
, cmd
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
)) {
60 real_exception(interp
, NULL
, NOSPAWN
, "Can't spawn child process");
63 WaitForSingleObject(pi
.hProcess
, INFINITE
);
65 if (!GetExitCodeProcess(pi
.hProcess
, &status
)) {
66 /* RT#48278 njs Should call GetLastError for failure message? */
67 Parrot_warn(interp
, PARROT_WARNINGS_PLATFORM_FLAG
,
68 "Process completed: Failed to get exit code.");
70 CloseHandle(pi
.hProcess
);
71 CloseHandle(pi
.hThread
);
72 if (free_it
) free(shell
);
75 /* Return exit code left shifted by 8 for POSIX emulation. */
82 Parrot_Run_OS_Command_Argv(Parrot_Interp interp, PMC *cmdargs)>
84 Spawns a subprocess with the arguments provided in the C<cmdargs> PMC array.
85 The first array element should be the name of the process to spawn,
86 and the remainder of the array elements should be arguments.
87 Waits until the child process completes,
88 and returns the exit code in POSIX-compatibility mode.
95 Parrot_Run_OS_Command_Argv(Parrot_Interp interp
, PMC
*cmdargs
)
99 PROCESS_INFORMATION pi
;
101 int cmdlinelen
= 1000;
103 char *cmdline
= mem_sys_allocate(cmdlinelen
);
106 /* Ensure there's something in the PMC array. */
107 pmclen
= VTABLE_elements(interp
, cmdargs
);
109 real_exception(interp
, NULL
, NOSPAWN
, "Empty argument array for spawnw");
112 /* Now build command line. */
113 for (i
= 0; i
< pmclen
; i
++) {
114 STRING
*s
= VTABLE_get_string_keyed_int(interp
, cmdargs
, i
);
115 char *cs
= string_to_cstring(interp
, s
);
116 if (cmdlinepos
+ (int)s
->strlen
+ 3 > cmdlinelen
) {
117 cmdlinelen
+= s
->strlen
+ 4;
118 cmdline
= mem_sys_realloc(cmdline
, cmdlinelen
);
120 strcpy(cmdline
+ cmdlinepos
, "\"");
121 strcpy(cmdline
+ cmdlinepos
+ 1, cs
);
122 strcpy(cmdline
+ cmdlinepos
+ 1 + s
->strlen
, "\" ");
123 cmdlinepos
+= s
->strlen
+ 3;
126 /* Start the child process. */
127 memset(&si
, 0, sizeof (si
));
129 memset(&pi
, 0, sizeof (pi
));
130 if (!CreateProcess(NULL
, cmdline
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
))
132 real_exception(interp
, NULL
, NOSPAWN
, "Can't spawn child process");
134 WaitForSingleObject(pi
.hProcess
, INFINITE
);
137 if (!GetExitCodeProcess(pi
.hProcess
, &status
)) {
138 /* RT#48278 njs Should call GetLastError for failure message? */
139 Parrot_warn(interp
, PARROT_WARNINGS_PLATFORM_FLAG
,
140 "Process completed: Failed to get exit code.");
144 CloseHandle(pi
.hProcess
);
145 CloseHandle(pi
.hThread
);
146 mem_sys_free(cmdline
);
148 /* Return exit code left shifted by 8 for POSIX emulation. */
155 Parrot_Exec_OS_Command(Parrot_Interp interp, STRING *command)>
157 Exits parrot and passes control to the specified process. Does not return. Raises an exception
165 Parrot_Exec_OS_Command(Parrot_Interp interp
, STRING
*command
)
168 char *in
= string_to_cstring(interp
, command
);
170 const char **argv
= mem_sys_allocate_zeroed(2 * sizeof (int));
172 /* Grab string, extract command and parameters. */
174 char *lastCommandStart
= in
;
179 /* If we don't have a seek character and this is a quote... */
180 if (seekChar
== 0 && (*curPos
== '\'' || *curPos
== '"'))
183 lastCommandStart
= curPos
;
186 /* If we don't have a seek character and this is not a space... */
187 else if (seekChar
== 0 && *curPos
!= ' ')
191 lastCommandStart
= curPos
;
194 /* If we seek the seek character... */
195 else if (*curPos
== seekChar
|| (*(curPos
+ 1) == 0 && seekChar
== ' '))
197 /* Copy what we found to a temporary string. */
199 int lenFound
= curPos
- lastCommandStart
;
200 if (*(curPos
+ 1) == 0)
202 tmp
= mem_sys_allocate(1 + lenFound
);
203 memcpy(tmp
, lastCommandStart
, lenFound
);
204 *(tmp
+ lenFound
) = 0;
206 /* Is it command or argument? */
214 /* Allocate space for another pointer in **argv. */
216 argv
= mem_sys_realloc(argv
, (argc
+ 1) * sizeof (int));
217 *(argv
+ (argc
- 1)) = tmp
;
218 *(argv
+ argc
) = NULL
;
221 /* Clear seek character. */
225 /* Move to next character. */
229 /* If we still have a seek char, then the input was improper. */
232 real_exception(interp
, NULL
, NOSPAWN
, "Exec failed, invalid command string");
235 /* Now do the exec. */
236 status
= _execvp(cmd
, argv
);
238 real_exception(interp
, NULL
, NOSPAWN
, "Exec failed, code %i", status
);
252 * c-file-style: "parrot"
254 * vim: expandtab shiftwidth=4: