279 lines
8.0 KiB
Factor
Executable File
279 lines
8.0 KiB
Factor
Executable File
! Copyright (C) 2007, 2010 Doug Coleman, Slava Pestov.
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
USING: accessors alien alien.c-types alien.data arrays assocs
|
|
classes classes.struct combinators concurrency.flags
|
|
continuations debugger destructors init io io.backend
|
|
io.backend.windows io.files io.files.private io.files.windows
|
|
io.launcher io.pathnames io.pipes io.pipes.windows io.ports
|
|
kernel libc locals make math namespaces prettyprint sequences
|
|
specialized-arrays splitting
|
|
strings system threads windows windows.errors windows.handles
|
|
windows.kernel32 windows.types ;
|
|
SPECIALIZED-ARRAY: ushort
|
|
SPECIALIZED-ARRAY: void*
|
|
IN: io.launcher.windows
|
|
|
|
TUPLE: CreateProcess-args
|
|
lpApplicationName
|
|
lpCommandLine
|
|
lpProcessAttributes
|
|
lpThreadAttributes
|
|
bInheritHandles
|
|
dwCreateFlags
|
|
lpEnvironment
|
|
lpCurrentDirectory
|
|
lpStartupInfo
|
|
lpProcessInformation ;
|
|
|
|
: default-CreateProcess-args ( -- obj )
|
|
CreateProcess-args new
|
|
STARTUPINFO <struct>
|
|
dup class heap-size >>cb
|
|
>>lpStartupInfo
|
|
PROCESS_INFORMATION <struct> >>lpProcessInformation
|
|
TRUE >>bInheritHandles
|
|
0 >>dwCreateFlags ;
|
|
|
|
: call-CreateProcess ( CreateProcess-args -- )
|
|
{
|
|
[ lpApplicationName>> ]
|
|
[ lpCommandLine>> ]
|
|
[ lpProcessAttributes>> ]
|
|
[ lpThreadAttributes>> ]
|
|
[ bInheritHandles>> ]
|
|
[ dwCreateFlags>> ]
|
|
[ lpEnvironment>> ]
|
|
[ lpCurrentDirectory>> ]
|
|
[ lpStartupInfo>> ]
|
|
[ lpProcessInformation>> ]
|
|
} cleave
|
|
CreateProcess win32-error=0/f ;
|
|
|
|
: count-trailing-backslashes ( str n -- str n )
|
|
[ "\\" ?tail ] dip swap [
|
|
1 + count-trailing-backslashes
|
|
] when ;
|
|
|
|
: fix-trailing-backslashes ( str -- str' )
|
|
0 count-trailing-backslashes
|
|
2 * CHAR: \\ <repetition> append ;
|
|
|
|
: escape-argument ( str -- newstr )
|
|
CHAR: \s over member? [
|
|
fix-trailing-backslashes "\"" dup surround
|
|
] when ;
|
|
|
|
: join-arguments ( args -- cmd-line )
|
|
[ escape-argument ] map " " join ;
|
|
|
|
: lookup-priority ( process -- n )
|
|
priority>> {
|
|
{ +lowest-priority+ [ IDLE_PRIORITY_CLASS ] }
|
|
{ +low-priority+ [ BELOW_NORMAL_PRIORITY_CLASS ] }
|
|
{ +normal-priority+ [ NORMAL_PRIORITY_CLASS ] }
|
|
{ +high-priority+ [ ABOVE_NORMAL_PRIORITY_CLASS ] }
|
|
{ +highest-priority+ [ HIGH_PRIORITY_CLASS ] }
|
|
{ +realtime-priority+ [ REALTIME_PRIORITY_CLASS ] }
|
|
[ drop f ]
|
|
} case ;
|
|
|
|
: app-name/cmd-line ( process -- app-name cmd-line )
|
|
command>> dup string? [
|
|
" " split1
|
|
] [
|
|
unclip swap join-arguments
|
|
] if ;
|
|
|
|
: cmd-line ( process -- cmd-line )
|
|
command>> dup string? [ join-arguments ] unless ;
|
|
|
|
: fill-lpApplicationName ( process args -- process args )
|
|
over app-name/cmd-line
|
|
[ >>lpApplicationName ] [ >>lpCommandLine ] bi* ;
|
|
|
|
: fill-lpCommandLine ( process args -- process args )
|
|
over cmd-line >>lpCommandLine ;
|
|
|
|
: fill-dwCreateFlags ( process args -- process args )
|
|
0
|
|
pick pass-environment? [ CREATE_UNICODE_ENVIRONMENT bitor ] when
|
|
pick detached>> os winnt? and [ DETACHED_PROCESS bitor ] when
|
|
pick lookup-priority [ bitor ] when*
|
|
>>dwCreateFlags ;
|
|
|
|
: fill-lpEnvironment ( process args -- process args )
|
|
over pass-environment? [
|
|
[
|
|
over get-environment
|
|
[ swap % "=" % % "\0" % ] assoc-each
|
|
"\0" %
|
|
] ushort-array{ } make
|
|
>>lpEnvironment
|
|
] when ;
|
|
|
|
: fill-startup-info ( process args -- process args )
|
|
dup lpStartupInfo>> STARTF_USESTDHANDLES >>dwFlags drop ;
|
|
|
|
HOOK: fill-redirection io-backend ( process args -- )
|
|
|
|
M: wince fill-redirection 2drop ;
|
|
|
|
: make-CreateProcess-args ( process -- args )
|
|
default-CreateProcess-args
|
|
os wince? [ fill-lpApplicationName ] [ fill-lpCommandLine ] if
|
|
fill-dwCreateFlags
|
|
fill-lpEnvironment
|
|
fill-startup-info
|
|
nip ;
|
|
|
|
M: windows current-process-handle ( -- handle )
|
|
GetCurrentProcessId ;
|
|
|
|
ERROR: launch-error process error ;
|
|
|
|
M: launch-error error.
|
|
"Launching failed with error:" print
|
|
dup error>> error. nl
|
|
"Launch descriptor:" print nl
|
|
process>> . ;
|
|
|
|
M: windows run-process* ( process -- handle )
|
|
[
|
|
[
|
|
current-directory get absolute-path cd
|
|
|
|
dup make-CreateProcess-args
|
|
[ fill-redirection ] keep
|
|
dup call-CreateProcess
|
|
lpProcessInformation>>
|
|
] with-destructors
|
|
] [ launch-error ] recover ;
|
|
|
|
M: windows kill-process* ( handle -- )
|
|
hProcess>> 255 TerminateProcess win32-error=0/f ;
|
|
|
|
: dispose-process ( process-information -- )
|
|
#! From MSDN: "Handles in PROCESS_INFORMATION must be closed
|
|
#! with CloseHandle when they are no longer needed."
|
|
[ hProcess>> [ CloseHandle drop ] when* ]
|
|
[ hThread>> [ CloseHandle drop ] when* ] bi ;
|
|
|
|
: exit-code ( process -- n )
|
|
hProcess>>
|
|
{ DWORD } [ GetExitCodeProcess ] with-out-parameters
|
|
swap win32-error=0/f ;
|
|
|
|
: process-exited ( process -- )
|
|
dup handle>> exit-code
|
|
over handle>> dispose-process
|
|
notify-exit ;
|
|
|
|
M: windows wait-for-processes ( -- ? )
|
|
processes get keys dup
|
|
[ handle>> hProcess>> ] void*-array{ } map-as
|
|
[ length ] keep 0 0
|
|
WaitForMultipleObjects
|
|
dup HEX: ffffffff = [ win32-error ] when
|
|
dup WAIT_TIMEOUT = [ 2drop t ] [ swap nth process-exited f ] if ;
|
|
|
|
: duplicate-handle ( handle -- handle' )
|
|
GetCurrentProcess ! source process
|
|
swap handle>> ! handle
|
|
GetCurrentProcess ! target process
|
|
f void* <ref> [ ! target handle
|
|
DUPLICATE_SAME_ACCESS ! desired access
|
|
TRUE ! inherit handle
|
|
0 ! options
|
|
DuplicateHandle win32-error=0/f
|
|
] keep void* deref <win32-handle> &dispose ;
|
|
|
|
! /dev/null simulation
|
|
: null-input ( -- pipe )
|
|
(pipe) [ in>> &dispose ] [ out>> dispose ] bi ;
|
|
|
|
: null-output ( -- pipe )
|
|
(pipe) [ out>> &dispose ] [ in>> dispose ] bi ;
|
|
|
|
: null-pipe ( mode -- pipe )
|
|
{
|
|
{ GENERIC_READ [ null-input ] }
|
|
{ GENERIC_WRITE [ null-output ] }
|
|
} case ;
|
|
|
|
! The below code is based on the example given in
|
|
! http://msdn2.microsoft.com/en-us/library/ms682499.aspx
|
|
|
|
: redirect-default ( obj access-mode create-mode -- handle )
|
|
3drop f ;
|
|
|
|
: redirect-closed ( obj access-mode create-mode -- handle )
|
|
drop nip null-pipe ;
|
|
|
|
:: redirect-file ( path access-mode create-mode -- handle )
|
|
path normalize-path
|
|
access-mode
|
|
share-mode
|
|
default-security-attributes
|
|
create-mode
|
|
FILE_ATTRIBUTE_NORMAL ! flags and attributes
|
|
f ! template file
|
|
CreateFile check-invalid-handle <win32-file> &dispose ;
|
|
|
|
: redirect-append ( path access-mode create-mode -- handle )
|
|
[ path>> ] 2dip
|
|
drop OPEN_ALWAYS
|
|
redirect-file
|
|
dup 0 FILE_END set-file-pointer ;
|
|
|
|
: redirect-handle ( handle access-mode create-mode -- handle )
|
|
2drop ;
|
|
|
|
: redirect-stream ( stream access-mode create-mode -- handle )
|
|
[ underlying-handle ] 2dip redirect-handle ;
|
|
|
|
: redirect ( obj access-mode create-mode -- handle )
|
|
{
|
|
{ [ pick not ] [ redirect-default ] }
|
|
{ [ pick +closed+ eq? ] [ redirect-closed ] }
|
|
{ [ pick string? ] [ redirect-file ] }
|
|
{ [ pick appender? ] [ redirect-append ] }
|
|
{ [ pick win32-file? ] [ redirect-handle ] }
|
|
[ redirect-stream ]
|
|
} cond
|
|
dup [ dup t set-inherit handle>> ] when ;
|
|
|
|
: redirect-stdout ( process args -- handle )
|
|
drop
|
|
stdout>>
|
|
GENERIC_WRITE
|
|
CREATE_ALWAYS
|
|
redirect
|
|
STD_OUTPUT_HANDLE GetStdHandle or ;
|
|
|
|
: redirect-stderr ( process args -- handle )
|
|
over stderr>> +stdout+ eq? [
|
|
nip
|
|
lpStartupInfo>> hStdOutput>>
|
|
] [
|
|
drop
|
|
stderr>>
|
|
GENERIC_WRITE
|
|
CREATE_ALWAYS
|
|
redirect
|
|
STD_ERROR_HANDLE GetStdHandle or
|
|
] if ;
|
|
|
|
: redirect-stdin ( process args -- handle )
|
|
drop
|
|
stdin>>
|
|
GENERIC_READ
|
|
OPEN_EXISTING
|
|
redirect
|
|
STD_INPUT_HANDLE GetStdHandle or ;
|
|
|
|
M: winnt fill-redirection ( process args -- )
|
|
dup lpStartupInfo>>
|
|
[ [ redirect-stdout ] dip hStdOutput<< ]
|
|
[ [ redirect-stderr ] dip hStdError<< ]
|
|
[ [ redirect-stdin ] dip hStdInput<< ] 3tri ;
|