#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <ctype.h>
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>
#include "spawn.h"
static void system_error( char const * name) {
// A function to retrieve, format, and print out a message from the
// last error. The `name' that's passed should be in the form of a
// present tense noun (phrase) such as "opening file".
//
char * ptr = NULL ;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
0 ,
GetLastError( ) ,
0 ,
( char * ) & ptr,
1024 ,
NULL ) ;
fprintf ( stderr , "%s\n " , ptr) ;
LocalFree( ptr) ;
}
static void InitializeInheritableSA( SECURITY_ATTRIBUTES * sa) {
sa- > nLength = sizeof * sa;
sa- > bInheritHandle = TRUE;
sa- > lpSecurityDescriptor = NULL ;
}
static HANDLE OpenInheritableFile( char const * name) {
SECURITY_ATTRIBUTES sa;
HANDLE retval;
InitializeInheritableSA( & sa) ;
retval = CreateFile(
name,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
& sa,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0 ) ;
if ( INVALID_HANDLE_VALUE == retval) {
char buffer[ 100 ] ;
sprintf ( buffer, "opening file %s" , name) ;
system_error( buffer) ;
return retval;
}
}
static HANDLE CreateInheritableFile( char const * name, int mode) {
SECURITY_ATTRIBUTES sa;
HANDLE retval;
DWORD FSmode = mode ? OPEN_ALWAYS : CREATE_NEW;
InitializeInheritableSA( & sa) ;
retval = CreateFile(
name,
GENERIC_WRITE,
FILE_SHARE_READ,
& sa,
FSmode,
FILE_ATTRIBUTE_NORMAL,
0 ) ;
if ( INVALID_HANDLE_VALUE == retval) {
char buffer[ 100 ] ;
sprintf ( buffer, "creating file %s" , name) ;
system_error( buffer) ;
return retval;
}
if ( mode == APPEND )
SetFilePointer( retval, 0 , 0 , FILE_END) ;
}
enum inheritance { inherit_read = 1 , inherit_write = 2 } ;
static BOOL CreateInheritablePipe( HANDLE * read, HANDLE * write, int inheritance) {
SECURITY_ATTRIBUTES sa;
InitializeInheritableSA( & sa) ;
if ( ! CreatePipe( read, write, & sa, 0 ) ) {
system_error( "Creating pipe" ) ;
return FALSE;
}
if ( ! inheritance & inherit_read)
DuplicateHandle(
GetCurrentProcess( ) ,
* read,
GetCurrentProcess( ) ,
NULL ,
0 ,
FALSE,
DUPLICATE_SAME_ACCESS) ;
if ( ! inheritance & inherit_write)
DuplicateHandle(
GetCurrentProcess( ) ,
* write,
GetCurrentProcess( ) ,
NULL ,
0 ,
FALSE,
DUPLICATE_SAME_ACCESS) ;
return TRUE;
}
static BOOL find_image( char const * name, char * buffer) {
// Try to find an image file named by the user.
// First search for the exact file name in the current
// directory. If that's found, look for same base name
// with ".com", ".exe" and ".bat" appended, in that order.
// If we can't find it in the current directory, repeat
// the entire process on directories specified in the
// PATH environment variable.
//
#define elements(array) (sizeof(array)/sizeof(array[0]))
static char * extensions[ ] = { ".com" , ".exe" , ".bat" , ".cmd" } ;
int i;
char temp[ FILENAME_MAX ] ;
if ( - 1 ! = access( name, 0 ) ) {
strcpy ( buffer, name) ;
return TRUE;
}
for ( i= 0 ; i< elements( extensions) ; i++ ) {
strcpy ( temp, name) ;
strcat ( temp, extensions[ i] ) ;
if ( - 1 ! = access( temp, 0 ) ) {
strcpy ( buffer, temp) ;
return TRUE;
}
}
_searchenv( name, "PATH" , buffer) ;
if ( buffer[ 0 ] ! = '\0 ' )
return TRUE;
for ( i= 0 ; i< elements( extensions) ; i++ ) {
strcpy ( temp, name) ;
strcat ( temp, extensions[ i] ) ;
_searchenv( temp, "PATH" , buffer) ;
if ( buffer[ 0 ] ! = '\0 ' )
return TRUE;
}
return FALSE;
}
static HANDLE DetachProcess( char const * name, HANDLE const * streams) {
STARTUPINFO s;
PROCESS_INFORMATION p;
char buffer[ FILENAME_MAX ] ;
memset ( & s, 0 , sizeof s) ;
s.cb = sizeof ( s) ;
s.dwFlags = STARTF_USESTDHANDLES;
s.hStdInput = streams[ 0 ] ;
s.hStdOutput = streams[ 1 ] ;
s.hStdError = streams[ 2 ] ;
if ( ! find_image( name, buffer) ) {
system_error( "Finding Image file" ) ;
return INVALID_HANDLE_VALUE;
}
// Since we've redirected the standard input, output and error handles
// of the child process, we create it without a console of its own.
// (That's the `DETACHED_PROCESS' part of the call.) Other
// possibilities include passing 0 so the child inherits our console,
// or passing CREATE_NEW_CONSOLE so the child gets a console of its
// own.
//
if ( ! CreateProcess(
NULL ,
buffer, NULL , NULL ,
TRUE,
DETACHED_PROCESS,
NULL , NULL ,
& s,
& p) )
{
system_error( "Spawning program" ) ;
return INVALID_HANDLE_VALUE;
}
// Since we don't need the handle to the child's thread, close it to
// save some resources.
CloseHandle( p.hThread ) ;
return p.hProcess ;
}
static HANDLE StartStreamHandler( ThrdProc proc, HANDLE stream) {
DWORD ignore;
return CreateThread(
NULL ,
0 ,
proc,
( void * ) stream,
0 ,
& ignore) ;
}
HANDLE CreateDetachedProcess( char const * name, stream_info * streams) {
// This Creates a detached process.
// First parameter: name of process to start.
// Second parameter: names of files to redirect the standard input, output and error
// streams of the child to (in that order.) Any file name that is NULL will be
// redirected to an anonymous pipe connected to the parent.
// Third Parameter: handles of the anonymous pipe(s) for the standard input, output
// and/or error streams of the new child process.
//
// Return value: a handle to the newly created process.
//
HANDLE child_handles[ 3 ] ;
HANDLE process;
int i;
// First handle the child's standard input. This is separate from the
// standard output and standard error because it's going the opposite
// direction. Basically, we create either a handle to a file the child
// will use, or else a pipe so the child can communicate with us.
//
if ( streams[ 0 ] .filename ! = NULL ) {
streams[ 0 ] .handle = NULL ;
child_handles[ 0 ] = OpenInheritableFile( streams[ 0 ] .filename ) ;
}
else
CreateInheritablePipe( child_handles, & ( streams[ 0 ] .handle ) , inherit_read) ;
// Now handle the child's standard output and standard error streams. These
// are separate from the code above simply because they go in the opposite
// direction.
//
for ( i= 1 ; i< 3 ; i++ )
if ( streams[ i] .filename ! = NULL ) {
streams[ i] .handle = NULL ;
child_handles[ i] = CreateInheritableFile( streams[ i] .filename , APPEND) ;
}
else
CreateInheritablePipe( & ( streams[ i] .handle ) , child_handles+ i, inherit_write) ;
// Now that we've set up the pipes and/or files the child's going to use,
// we're ready to actually start up the child process:
process = DetachProcess( name, child_handles) ;
if ( INVALID_HANDLE_VALUE == process)
return process;
// Now that we've started the child, we close our handles to its ends of the pipes.
// If one or more of these happens to a handle to a file instead, it doesn't really
// need to be closed, but it doesn't hurt either. However, with the child's standard
// output and standard error streams, it's CRUCIAL to close our handles if either is a
// handle to a pipe. The system detects the end of data on a pipe when ALL handles to
// the write end of the pipe are closed -- if we still have an open handle to the
// write end of one of these pipes, we won't be able to detect when the child is done
// writing to the pipe.
//
for ( i= 0 ; i< 3 ; i++ ) {
CloseHandle( child_handles[ i] ) ;
if ( streams[ i] .handler )
streams[ i] .handle =
StartStreamHandler( streams[ i] .handler , streams[ i] .handle ) ;
}
return process;
}
#ifdef TEST
#define buf_size 256
unsigned long __stdcall handle_error( void * pipe) {
// The control (and only) function for a thread handling the standard
// error from the child process. We'll handle it by displaying a
// message box each time we receive data on the standard error stream.
//
char buffer[ buf_size] ;
HANDLE child_error_rd = ( HANDLE) pipe;
unsigned bytes;
while ( ERROR_BROKEN_PIPE ! = GetLastError( ) &&
ReadFile( child_error_rd, buffer, 256 , & bytes, NULL ) )
{
buffer[ bytes+ 1 ] = '\0 ' ;
MessageBox( NULL , buffer, "Error" , MB_OK) ;
}
return 0 ;
}
unsigned long __stdcall handle_output( void * pipe) {
// A similar thread function to handle standard output from the child
// process. Nothing special is done with the output - it's simply
// displayed in our console. However, just for fun it opens a C high-
// level FILE * for the handle, and uses fgets to read it. As
// expected, fgets detects the broken pipe as the end of the file.
//
char buffer[ buf_size] ;
int handle;
FILE * file;
handle = _open_osfhandle( ( long ) pipe, _O_RDONLY | _O_BINARY) ;
file = _fdopen( handle, "r" ) ;
if ( NULL == file )
return 1 ;
while ( fgets ( buffer, buf_size, file) )
printf ( "%s" , buffer) ;
return 0 ;
}
int main( int argc, char ** argv) {
stream_info streams[ 3 ] ;
HANDLE handles[ 3 ] ;
int i;
if ( argc < 3 ) {
fputs ( "Usage: spawn prog datafile"
"\n which will spawn `prog' with its standard input set to"
"\n read from `datafile'. Then `prog's standard output"
"\n will be captured and printed. If `prog' writes to its"
"\n standard error, that output will be displayed in a"
"\n MessageBox.\n " ,
stderr ) ;
return 1 ;
}
memset ( streams, 0 , sizeof ( streams) ) ;
streams[ 0 ] .filename = argv[ 2 ] ;
streams[ 1 ] .handler = handle_output;
streams[ 2 ] .handler = handle_error;
handles[ 0 ] = CreateDetachedProcess( argv[ 1 ] , streams) ;
handles[ 1 ] = streams[ 1 ] .handle ;
handles[ 2 ] = streams[ 2 ] .handle ;
WaitForMultipleObjects( 3 , handles, TRUE, INFINITE) ;
for ( i= 0 ; i< 3 ; i++ )
CloseHandle( handles[ i] ) ;
return 0 ;
}
#endif
I2RlZmluZSBTVFJJQ1QKI2RlZmluZSBXSU4zMl9MRUFOX0FORF9NRUFOCiNpbmNsdWRlIDx3aW5kb3dzLmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KI2luY2x1ZGUgPGlvLmg+CiNpbmNsdWRlIDxmY250bC5oPgojaW5jbHVkZSA8c3RkbGliLmg+CgojaW5jbHVkZSAic3Bhd24uaCIKCnN0YXRpYyB2b2lkIHN5c3RlbV9lcnJvcihjaGFyIGNvbnN0ICpuYW1lKSB7Ci8vIEEgZnVuY3Rpb24gdG8gcmV0cmlldmUsIGZvcm1hdCwgYW5kIHByaW50IG91dCBhIG1lc3NhZ2UgZnJvbSB0aGUKLy8gbGFzdCBlcnJvci4gIFRoZSBgbmFtZScgdGhhdCdzIHBhc3NlZCBzaG91bGQgYmUgaW4gdGhlIGZvcm0gb2YgYQovLyBwcmVzZW50IHRlbnNlIG5vdW4gKHBocmFzZSkgc3VjaCBhcyAib3BlbmluZyBmaWxlIi4KLy8KICAgIGNoYXIgKnB0ciA9IE5VTEw7CiAgICBGb3JtYXRNZXNzYWdlKAogICAgICAgIEZPUk1BVF9NRVNTQUdFX0FMTE9DQVRFX0JVRkZFUiB8CiAgICAgICAgRk9STUFUX01FU1NBR0VfRlJPTV9TWVNURU0sCiAgICAgICAgMCwKICAgICAgICBHZXRMYXN0RXJyb3IoKSwKICAgICAgICAwLAogICAgICAgIChjaGFyICopJnB0ciwKICAgICAgICAxMDI0LAogICAgICAgIE5VTEwpOwoKICAgIGZwcmludGYoc3RkZXJyLCAiJXNcbiIsIHB0cik7CiAgICBMb2NhbEZyZWUocHRyKTsKfQoKc3RhdGljIHZvaWQgSW5pdGlhbGl6ZUluaGVyaXRhYmxlU0EoU0VDVVJJVFlfQVRUUklCVVRFUyAqc2EpIHsKCiAgICBzYS0+bkxlbmd0aCA9IHNpemVvZiAqc2E7CiAgICBzYS0+YkluaGVyaXRIYW5kbGUgPSBUUlVFOwogICAgc2EtPmxwU2VjdXJpdHlEZXNjcmlwdG9yID0gTlVMTDsKfQoKCnN0YXRpYyBIQU5ETEUgT3BlbkluaGVyaXRhYmxlRmlsZShjaGFyIGNvbnN0ICpuYW1lKSB7CiAgICBTRUNVUklUWV9BVFRSSUJVVEVTIHNhOwogICAgSEFORExFIHJldHZhbDsKCiAgICBJbml0aWFsaXplSW5oZXJpdGFibGVTQSgmc2EpOwoKICAgIHJldHZhbCA9IENyZWF0ZUZpbGUoCiAgICAgICAgbmFtZSwKICAgICAgICBHRU5FUklDX1JFQUQsCiAgICAgICAgRklMRV9TSEFSRV9SRUFEIHwgRklMRV9TSEFSRV9XUklURSwKICAgICAgICAmc2EsCiAgICAgICAgT1BFTl9FWElTVElORywKICAgICAgICBGSUxFX0FUVFJJQlVURV9OT1JNQUwsCiAgICAgICAgMCk7CgoKICAgIGlmIChJTlZBTElEX0hBTkRMRV9WQUxVRSA9PSByZXR2YWwpIHsKICAgICAgICBjaGFyIGJ1ZmZlclsxMDBdOwoKICAgICAgICBzcHJpbnRmKGJ1ZmZlciwgIm9wZW5pbmcgZmlsZSAlcyIsIG5hbWUpOwoKICAgICAgICBzeXN0ZW1fZXJyb3IoYnVmZmVyKTsKICAgICAgICByZXR1cm4gcmV0dmFsOwogICAgfQp9CgpzdGF0aWMgSEFORExFIENyZWF0ZUluaGVyaXRhYmxlRmlsZShjaGFyIGNvbnN0ICpuYW1lLCBpbnQgbW9kZSkgewogICAgU0VDVVJJVFlfQVRUUklCVVRFUyBzYTsKICAgIEhBTkRMRSByZXR2YWw7CgogICAgRFdPUkQgRlNtb2RlID0gbW9kZSA/IE9QRU5fQUxXQVlTIDogQ1JFQVRFX05FVzsKCiAgICBJbml0aWFsaXplSW5oZXJpdGFibGVTQSgmc2EpOwoKICAgIHJldHZhbCA9IENyZWF0ZUZpbGUoCiAgICAgICAgbmFtZSwKICAgICAgICBHRU5FUklDX1dSSVRFLAogICAgICAgIEZJTEVfU0hBUkVfUkVBRCwKICAgICAgICAmc2EsCiAgICAgICAgRlNtb2RlLAogICAgICAgIEZJTEVfQVRUUklCVVRFX05PUk1BTCwKICAgICAgICAwKTsKCiAgICBpZiAoSU5WQUxJRF9IQU5ETEVfVkFMVUUgPT0gcmV0dmFsKSB7CiAgICAgICAgY2hhciBidWZmZXJbMTAwXTsKCiAgICAgICAgc3ByaW50ZihidWZmZXIsICJjcmVhdGluZyBmaWxlICVzIiwgbmFtZSk7CgogICAgICAgIHN5c3RlbV9lcnJvcihidWZmZXIpOwogICAgICAgIHJldHVybiByZXR2YWw7CiAgICB9CiAgICAKICAgIGlmICggbW9kZSA9PSBBUFBFTkQgKSAKICAgICAgICBTZXRGaWxlUG9pbnRlcihyZXR2YWwsIDAsIDAsIEZJTEVfRU5EKTsKfQoKZW51bSBpbmhlcml0YW5jZSB7IGluaGVyaXRfcmVhZCA9IDEsIGluaGVyaXRfd3JpdGUgPSAyIH07CgpzdGF0aWMgQk9PTCBDcmVhdGVJbmhlcml0YWJsZVBpcGUoSEFORExFICpyZWFkLCBIQU5ETEUgKndyaXRlLCBpbnQgaW5oZXJpdGFuY2UpIHsKCiAgICBTRUNVUklUWV9BVFRSSUJVVEVTIHNhOwoKICAgIEluaXRpYWxpemVJbmhlcml0YWJsZVNBKCZzYSk7CgogICAgaWYgKCAhQ3JlYXRlUGlwZShyZWFkLCB3cml0ZSwgJnNhLCAwKSkgewogICAgICAgIHN5c3RlbV9lcnJvcigiQ3JlYXRpbmcgcGlwZSIpOwogICAgICAgIHJldHVybiBGQUxTRTsKICAgIH0KCiAgICBpZiAoIWluaGVyaXRhbmNlICYgaW5oZXJpdF9yZWFkKQogICAgICAgIER1cGxpY2F0ZUhhbmRsZSgKICAgICAgICAgICAgR2V0Q3VycmVudFByb2Nlc3MoKSwKICAgICAgICAgICAgKnJlYWQsCiAgICAgICAgICAgIEdldEN1cnJlbnRQcm9jZXNzKCksCiAgICAgICAgICAgIE5VTEwsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIEZBTFNFLAogICAgICAgICAgICBEVVBMSUNBVEVfU0FNRV9BQ0NFU1MpOwoKICAgIGlmICghaW5oZXJpdGFuY2UgJiBpbmhlcml0X3dyaXRlKSAKICAgICAgICBEdXBsaWNhdGVIYW5kbGUoCiAgICAgICAgICAgIEdldEN1cnJlbnRQcm9jZXNzKCksCiAgICAgICAgICAgICp3cml0ZSwKICAgICAgICAgICAgR2V0Q3VycmVudFByb2Nlc3MoKSwKICAgICAgICAgICAgTlVMTCwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgRkFMU0UsCiAgICAgICAgICAgIERVUExJQ0FURV9TQU1FX0FDQ0VTUyk7CgogICAgcmV0dXJuIFRSVUU7Cn0KCnN0YXRpYyBCT09MIGZpbmRfaW1hZ2UoY2hhciBjb25zdCAqbmFtZSwgY2hhciAqYnVmZmVyKSB7Ci8vIFRyeSB0byBmaW5kIGFuIGltYWdlIGZpbGUgbmFtZWQgYnkgdGhlIHVzZXIuCi8vIEZpcnN0IHNlYXJjaCBmb3IgdGhlIGV4YWN0IGZpbGUgbmFtZSBpbiB0aGUgY3VycmVudAovLyBkaXJlY3RvcnkuICBJZiB0aGF0J3MgZm91bmQsIGxvb2sgZm9yIHNhbWUgYmFzZSBuYW1lCi8vIHdpdGggIi5jb20iLCAiLmV4ZSIgYW5kICIuYmF0IiBhcHBlbmRlZCwgaW4gdGhhdCBvcmRlci4KLy8gSWYgd2UgY2FuJ3QgZmluZCBpdCBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnksIHJlcGVhdAovLyB0aGUgZW50aXJlIHByb2Nlc3Mgb24gZGlyZWN0b3JpZXMgc3BlY2lmaWVkIGluIHRoZQovLyBQQVRIIGVudmlyb25tZW50IHZhcmlhYmxlLgovLwojZGVmaW5lIGVsZW1lbnRzKGFycmF5KSAoc2l6ZW9mKGFycmF5KS9zaXplb2YoYXJyYXlbMF0pKQoKICAgIHN0YXRpYyBjaGFyICpleHRlbnNpb25zW10gPSB7Ii5jb20iLCAiLmV4ZSIsICIuYmF0IiwgIi5jbWQifTsKICAgIGludCBpOwogICAgY2hhciB0ZW1wW0ZJTEVOQU1FX01BWF07CgogICAgaWYgKC0xICE9IGFjY2VzcyhuYW1lLCAwKSkgewogICAgICAgIHN0cmNweShidWZmZXIsIG5hbWUpOwogICAgICAgIHJldHVybiBUUlVFOwogICAgfQoKICAgIGZvciAoaT0wOyBpPGVsZW1lbnRzKGV4dGVuc2lvbnMpOyBpKyspIHsKICAgICAgICBzdHJjcHkodGVtcCwgbmFtZSk7CiAgICAgICAgc3RyY2F0KHRlbXAsIGV4dGVuc2lvbnNbaV0pOwogICAgICAgIGlmICggLTEgIT0gYWNjZXNzKHRlbXAsIDApKSB7CiAgICAgICAgICAgIHN0cmNweShidWZmZXIsIHRlbXApOwogICAgICAgICAgICByZXR1cm4gVFJVRTsKICAgICAgICB9CiAgICB9CgogICAgX3NlYXJjaGVudihuYW1lLCAiUEFUSCIsIGJ1ZmZlcik7CiAgICBpZiAoIGJ1ZmZlclswXSAhPSAnXDAnKQogICAgICAgIHJldHVybiBUUlVFOwoKICAgIGZvciAoIGk9MDsgaTxlbGVtZW50cyhleHRlbnNpb25zKTsgaSsrKSB7CiAgICAgICAgc3RyY3B5KHRlbXAsIG5hbWUpOwogICAgICAgIHN0cmNhdCh0ZW1wLCBleHRlbnNpb25zW2ldKTsKICAgICAgICBfc2VhcmNoZW52KHRlbXAsICJQQVRIIiwgYnVmZmVyKTsKICAgICAgICBpZiAoIGJ1ZmZlclswXSAhPSAnXDAnKQogICAgICAgICAgICByZXR1cm4gVFJVRTsKICAgIH0KCiAgICByZXR1cm4gRkFMU0U7Cn0KCgpzdGF0aWMgSEFORExFIERldGFjaFByb2Nlc3MoY2hhciBjb25zdCAqbmFtZSwgSEFORExFIGNvbnN0ICpzdHJlYW1zKSB7CiAgICBTVEFSVFVQSU5GTyBzOwogICAgUFJPQ0VTU19JTkZPUk1BVElPTiBwOwogICAgY2hhciBidWZmZXJbRklMRU5BTUVfTUFYXTsKCiAgICBtZW1zZXQoJnMsIDAsIHNpemVvZiBzKTsKICAgIHMuY2IgPSBzaXplb2Yocyk7CiAgICBzLmR3RmxhZ3MgPSBTVEFSVEZfVVNFU1RESEFORExFUzsKICAgIHMuaFN0ZElucHV0ID0gc3RyZWFtc1swXTsKICAgIHMuaFN0ZE91dHB1dCA9IHN0cmVhbXNbMV07CiAgICBzLmhTdGRFcnJvciA9IHN0cmVhbXNbMl07CgogICAgaWYgKCAhZmluZF9pbWFnZShuYW1lLCBidWZmZXIpKSB7CiAgICAgICAgc3lzdGVtX2Vycm9yKCJGaW5kaW5nIEltYWdlIGZpbGUiKTsKICAgICAgICByZXR1cm4gSU5WQUxJRF9IQU5ETEVfVkFMVUU7CiAgICB9CgovLyBTaW5jZSB3ZSd2ZSByZWRpcmVjdGVkIHRoZSBzdGFuZGFyZCBpbnB1dCwgb3V0cHV0IGFuZCBlcnJvciBoYW5kbGVzCi8vIG9mIHRoZSBjaGlsZCBwcm9jZXNzLCB3ZSBjcmVhdGUgaXQgd2l0aG91dCBhIGNvbnNvbGUgb2YgaXRzIG93bi4KLy8gKFRoYXQncyB0aGUgYERFVEFDSEVEX1BST0NFU1MnIHBhcnQgb2YgdGhlIGNhbGwuKSAgT3RoZXIKLy8gcG9zc2liaWxpdGllcyBpbmNsdWRlIHBhc3NpbmcgMCBzbyB0aGUgY2hpbGQgaW5oZXJpdHMgb3VyIGNvbnNvbGUsCi8vIG9yIHBhc3NpbmcgQ1JFQVRFX05FV19DT05TT0xFIHNvIHRoZSBjaGlsZCBnZXRzIGEgY29uc29sZSBvZiBpdHMKLy8gb3duLgovLwogICAgaWYgKCFDcmVhdGVQcm9jZXNzKAogICAgICAgIE5VTEwsCiAgICAgICAgYnVmZmVyLCBOVUxMLCBOVUxMLAogICAgICAgIFRSVUUsCiAgICAgICAgREVUQUNIRURfUFJPQ0VTUywKICAgICAgICBOVUxMLCBOVUxMLAogICAgICAgICZzLAogICAgICAgICZwKSkKICAgIHsKICAgICAgICBzeXN0ZW1fZXJyb3IoIlNwYXduaW5nIHByb2dyYW0iKTsKICAgICAgICByZXR1cm4gSU5WQUxJRF9IQU5ETEVfVkFMVUU7CiAgICB9CgovLyBTaW5jZSB3ZSBkb24ndCBuZWVkIHRoZSBoYW5kbGUgdG8gdGhlIGNoaWxkJ3MgdGhyZWFkLCBjbG9zZSBpdCB0bwovLyBzYXZlIHNvbWUgcmVzb3VyY2VzLgogICAgQ2xvc2VIYW5kbGUocC5oVGhyZWFkKTsKCiAgICByZXR1cm4gcC5oUHJvY2VzczsKfQoKc3RhdGljIEhBTkRMRSBTdGFydFN0cmVhbUhhbmRsZXIoVGhyZFByb2MgcHJvYywgSEFORExFIHN0cmVhbSkgewoKICAgIERXT1JEIGlnbm9yZTsKCiAgICByZXR1cm4gQ3JlYXRlVGhyZWFkKAogICAgICAgIE5VTEwsCiAgICAgICAgMCwKICAgICAgICBwcm9jLAogICAgICAgICh2b2lkICopc3RyZWFtLAogICAgICAgIDAsCiAgICAgICAgJmlnbm9yZSk7Cn0KCkhBTkRMRSBDcmVhdGVEZXRhY2hlZFByb2Nlc3MoY2hhciBjb25zdCAqbmFtZSwgc3RyZWFtX2luZm8gKnN0cmVhbXMpIHsKLy8gVGhpcyBDcmVhdGVzIGEgZGV0YWNoZWQgcHJvY2Vzcy4KLy8gRmlyc3QgcGFyYW1ldGVyOiBuYW1lIG9mIHByb2Nlc3MgdG8gc3RhcnQuCi8vIFNlY29uZCBwYXJhbWV0ZXI6IG5hbWVzIG9mIGZpbGVzIHRvIHJlZGlyZWN0IHRoZSBzdGFuZGFyZCBpbnB1dCwgb3V0cHV0IGFuZCBlcnJvciAKLy8gIHN0cmVhbXMgb2YgdGhlIGNoaWxkIHRvIChpbiB0aGF0IG9yZGVyLikgIEFueSBmaWxlIG5hbWUgdGhhdCBpcyBOVUxMIHdpbGwgYmUgCi8vICByZWRpcmVjdGVkIHRvIGFuIGFub255bW91cyBwaXBlIGNvbm5lY3RlZCB0byB0aGUgcGFyZW50LgovLyBUaGlyZCBQYXJhbWV0ZXI6IGhhbmRsZXMgb2YgdGhlIGFub255bW91cyBwaXBlKHMpIGZvciB0aGUgc3RhbmRhcmQgaW5wdXQsIG91dHB1dAovLyBhbmQvb3IgZXJyb3Igc3RyZWFtcyBvZiB0aGUgbmV3IGNoaWxkIHByb2Nlc3MuCi8vCi8vIFJldHVybiB2YWx1ZTogYSBoYW5kbGUgdG8gdGhlIG5ld2x5IGNyZWF0ZWQgcHJvY2Vzcy4KLy8KCiAgICBIQU5ETEUgY2hpbGRfaGFuZGxlc1szXTsKICAgIEhBTkRMRSBwcm9jZXNzOwoKICAgIGludCBpOwoKLy8gRmlyc3QgaGFuZGxlIHRoZSBjaGlsZCdzIHN0YW5kYXJkIGlucHV0LiAgVGhpcyBpcyBzZXBhcmF0ZSBmcm9tIHRoZSAKLy8gc3RhbmRhcmQgb3V0cHV0IGFuZCBzdGFuZGFyZCBlcnJvciBiZWNhdXNlIGl0J3MgZ29pbmcgdGhlIG9wcG9zaXRlIAovLyBkaXJlY3Rpb24uICBCYXNpY2FsbHksIHdlIGNyZWF0ZSBlaXRoZXIgYSBoYW5kbGUgdG8gYSBmaWxlIHRoZSBjaGlsZAovLyB3aWxsIHVzZSwgb3IgZWxzZSBhIHBpcGUgc28gdGhlIGNoaWxkIGNhbiBjb21tdW5pY2F0ZSB3aXRoIHVzLgovLyAKICAgIGlmICggc3RyZWFtc1swXS5maWxlbmFtZSAhPSBOVUxMICkgewogICAgICAgIHN0cmVhbXNbMF0uaGFuZGxlID0gTlVMTDsKICAgICAgICBjaGlsZF9oYW5kbGVzWzBdID0gT3BlbkluaGVyaXRhYmxlRmlsZShzdHJlYW1zWzBdLmZpbGVuYW1lKTsKICAgIH0KICAgIGVsc2UKICAgICAgICBDcmVhdGVJbmhlcml0YWJsZVBpcGUoY2hpbGRfaGFuZGxlcywgJihzdHJlYW1zWzBdLmhhbmRsZSksIGluaGVyaXRfcmVhZCk7CgovLyBOb3cgaGFuZGxlIHRoZSBjaGlsZCdzIHN0YW5kYXJkIG91dHB1dCBhbmQgc3RhbmRhcmQgZXJyb3Igc3RyZWFtcy4gIFRoZXNlCi8vIGFyZSBzZXBhcmF0ZSBmcm9tIHRoZSBjb2RlIGFib3ZlIHNpbXBseSBiZWNhdXNlIHRoZXkgZ28gaW4gdGhlIG9wcG9zaXRlIAovLyBkaXJlY3Rpb24uCi8vCiAgICBmb3IgKCBpPTE7IGk8MzsgaSsrKSAKICAgICAgICBpZiAoIHN0cmVhbXNbaV0uZmlsZW5hbWUgIT0gTlVMTCkgewogICAgICAgICAgICBzdHJlYW1zW2ldLmhhbmRsZSA9IE5VTEw7CiAgICAgICAgICAgIGNoaWxkX2hhbmRsZXNbaV0gPSBDcmVhdGVJbmhlcml0YWJsZUZpbGUoc3RyZWFtc1tpXS5maWxlbmFtZSwgQVBQRU5EKTsKICAgICAgICB9CiAgICAgICAgZWxzZSAKICAgICAgICAgICAgQ3JlYXRlSW5oZXJpdGFibGVQaXBlKCYoc3RyZWFtc1tpXS5oYW5kbGUpLCBjaGlsZF9oYW5kbGVzK2ksIGluaGVyaXRfd3JpdGUpOwoKLy8gTm93IHRoYXQgd2UndmUgc2V0IHVwIHRoZSBwaXBlcyBhbmQvb3IgZmlsZXMgdGhlIGNoaWxkJ3MgZ29pbmcgdG8gdXNlLAovLyB3ZSdyZSByZWFkeSB0byBhY3R1YWxseSBzdGFydCB1cCB0aGUgY2hpbGQgcHJvY2VzczoKICAgIHByb2Nlc3MgPSBEZXRhY2hQcm9jZXNzKG5hbWUsIGNoaWxkX2hhbmRsZXMpOwogICAgaWYgKElOVkFMSURfSEFORExFX1ZBTFVFID09IHByb2Nlc3MpCiAgICAgICAgcmV0dXJuIHByb2Nlc3M7CgovLyBOb3cgdGhhdCB3ZSd2ZSBzdGFydGVkIHRoZSBjaGlsZCwgd2UgY2xvc2Ugb3VyIGhhbmRsZXMgdG8gaXRzIGVuZHMgb2YgdGhlIHBpcGVzLgovLyBJZiBvbmUgb3IgbW9yZSBvZiB0aGVzZSBoYXBwZW5zIHRvIGEgaGFuZGxlIHRvIGEgZmlsZSBpbnN0ZWFkLCBpdCBkb2Vzbid0IHJlYWxseSAKLy8gbmVlZCB0byBiZSBjbG9zZWQsIGJ1dCBpdCBkb2Vzbid0IGh1cnQgZWl0aGVyLiAgSG93ZXZlciwgd2l0aCB0aGUgY2hpbGQncyBzdGFuZGFyZAovLyBvdXRwdXQgYW5kIHN0YW5kYXJkIGVycm9yIHN0cmVhbXMsIGl0J3MgQ1JVQ0lBTCB0byBjbG9zZSBvdXIgaGFuZGxlcyBpZiBlaXRoZXIgaXMgYQovLyBoYW5kbGUgdG8gYSBwaXBlLiAgVGhlIHN5c3RlbSBkZXRlY3RzIHRoZSBlbmQgb2YgZGF0YSBvbiBhIHBpcGUgd2hlbiBBTEwgaGFuZGxlcyB0bwovLyB0aGUgd3JpdGUgZW5kIG9mIHRoZSBwaXBlIGFyZSBjbG9zZWQgLS0gaWYgd2Ugc3RpbGwgaGF2ZSBhbiBvcGVuIGhhbmRsZSB0byB0aGUKLy8gd3JpdGUgZW5kIG9mIG9uZSBvZiB0aGVzZSBwaXBlcywgd2Ugd29uJ3QgYmUgYWJsZSB0byBkZXRlY3Qgd2hlbiB0aGUgY2hpbGQgaXMgZG9uZQovLyB3cml0aW5nIHRvIHRoZSBwaXBlLgovLwogICAgZm9yICggaT0wOyBpPDM7IGkrKykgewogICAgICAgIENsb3NlSGFuZGxlKGNoaWxkX2hhbmRsZXNbaV0pOwogICAgICAgIGlmICggc3RyZWFtc1tpXS5oYW5kbGVyICkgCiAgICAgICAgICAgIHN0cmVhbXNbaV0uaGFuZGxlID0gCiAgICAgICAgICAgICAgICBTdGFydFN0cmVhbUhhbmRsZXIoc3RyZWFtc1tpXS5oYW5kbGVyLCBzdHJlYW1zW2ldLmhhbmRsZSk7CiAgICB9CiAgICByZXR1cm4gcHJvY2VzczsKfQoKI2lmZGVmIFRFU1QKCiNkZWZpbmUgYnVmX3NpemUgMjU2Cgp1bnNpZ25lZCBsb25nIF9fc3RkY2FsbCBoYW5kbGVfZXJyb3Iodm9pZCAqcGlwZSkgewovLyBUaGUgY29udHJvbCAoYW5kIG9ubHkpIGZ1bmN0aW9uIGZvciBhIHRocmVhZCBoYW5kbGluZyB0aGUgc3RhbmRhcmQKLy8gZXJyb3IgZnJvbSB0aGUgY2hpbGQgcHJvY2Vzcy4gIFdlJ2xsIGhhbmRsZSBpdCBieSBkaXNwbGF5aW5nIGEKLy8gbWVzc2FnZSBib3ggZWFjaCB0aW1lIHdlIHJlY2VpdmUgZGF0YSBvbiB0aGUgc3RhbmRhcmQgZXJyb3Igc3RyZWFtLgovLwogICAgY2hhciBidWZmZXJbYnVmX3NpemVdOwogICAgSEFORExFIGNoaWxkX2Vycm9yX3JkID0gKEhBTkRMRSlwaXBlOwogICAgdW5zaWduZWQgYnl0ZXM7CgogICAgd2hpbGUgKEVSUk9SX0JST0tFTl9QSVBFICE9IEdldExhc3RFcnJvcigpICYmCiAgICAgICAgUmVhZEZpbGUoY2hpbGRfZXJyb3JfcmQsIGJ1ZmZlciwgMjU2LCAmYnl0ZXMsIE5VTEwpKQogICAgewogICAgICAgIGJ1ZmZlcltieXRlcysxXSA9ICdcMCc7CiAgICAgICAgTWVzc2FnZUJveChOVUxMLCBidWZmZXIsICJFcnJvciIsIE1CX09LKTsKICAgIH0KICAgIHJldHVybiAwOwp9Cgp1bnNpZ25lZCBsb25nIF9fc3RkY2FsbCBoYW5kbGVfb3V0cHV0KHZvaWQgKnBpcGUpIHsKLy8gQSBzaW1pbGFyIHRocmVhZCBmdW5jdGlvbiB0byBoYW5kbGUgc3RhbmRhcmQgb3V0cHV0IGZyb20gdGhlIGNoaWxkCi8vIHByb2Nlc3MuICBOb3RoaW5nIHNwZWNpYWwgaXMgZG9uZSB3aXRoIHRoZSBvdXRwdXQgLSBpdCdzIHNpbXBseQovLyBkaXNwbGF5ZWQgaW4gb3VyIGNvbnNvbGUuICBIb3dldmVyLCBqdXN0IGZvciBmdW4gaXQgb3BlbnMgYSBDIGhpZ2gtCi8vIGxldmVsIEZJTEUgKiBmb3IgdGhlIGhhbmRsZSwgYW5kIHVzZXMgZmdldHMgdG8gcmVhZCBpdC4gIEFzCi8vIGV4cGVjdGVkLCBmZ2V0cyBkZXRlY3RzIHRoZSBicm9rZW4gcGlwZSBhcyB0aGUgZW5kIG9mIHRoZSBmaWxlLgovLwogICAgY2hhciBidWZmZXJbYnVmX3NpemVdOwogICAgaW50IGhhbmRsZTsKICAgIEZJTEUgKmZpbGU7CgogICAgaGFuZGxlID0gX29wZW5fb3NmaGFuZGxlKChsb25nKXBpcGUsIF9PX1JET05MWSB8IF9PX0JJTkFSWSk7CiAgICBmaWxlID0gX2Zkb3BlbihoYW5kbGUsICJyIik7CgogICAgaWYgKCBOVUxMID09IGZpbGUgKQogICAgICAgIHJldHVybiAxOwoKICAgIHdoaWxlICggZmdldHMoYnVmZmVyLCBidWZfc2l6ZSwgZmlsZSkpCiAgICAgICAgcHJpbnRmKCIlcyIsIGJ1ZmZlcik7CgogICAgcmV0dXJuIDA7Cn0KCmludCBtYWluKGludCBhcmdjLCBjaGFyICoqYXJndikgewoKICAgIHN0cmVhbV9pbmZvIHN0cmVhbXNbM107CiAgICBIQU5ETEUgaGFuZGxlc1szXTsKICAgIGludCBpOwoKICAgIGlmICggYXJnYyA8IDMgKSB7CiAgICAgICAgZnB1dHMoIlVzYWdlOiBzcGF3biBwcm9nIGRhdGFmaWxlIgogICAgICAgICAgICAiXG53aGljaCB3aWxsIHNwYXduIGBwcm9nJyB3aXRoIGl0cyBzdGFuZGFyZCBpbnB1dCBzZXQgdG8iCiAgICAgICAgICAgICJcbnJlYWQgZnJvbSBgZGF0YWZpbGUnLiAgVGhlbiBgcHJvZydzIHN0YW5kYXJkIG91dHB1dCIKICAgICAgICAgICAgIlxud2lsbCBiZSBjYXB0dXJlZCBhbmQgcHJpbnRlZC4gIElmIGBwcm9nJyB3cml0ZXMgdG8gaXRzIgogICAgICAgICAgICAiXG5zdGFuZGFyZCBlcnJvciwgdGhhdCBvdXRwdXQgd2lsbCBiZSBkaXNwbGF5ZWQgaW4gYSIKICAgICAgICAgICAgIlxuTWVzc2FnZUJveC5cbiIsCiAgICAgICAgICAgICAgICBzdGRlcnIpOwogICAgICAgIHJldHVybiAxOwogICAgfQoKICAgIG1lbXNldChzdHJlYW1zLCAwLCBzaXplb2Yoc3RyZWFtcykpOwoKICAgIHN0cmVhbXNbMF0uZmlsZW5hbWUgPSBhcmd2WzJdOwogICAgc3RyZWFtc1sxXS5oYW5kbGVyID0gaGFuZGxlX291dHB1dDsKICAgIHN0cmVhbXNbMl0uaGFuZGxlciA9IGhhbmRsZV9lcnJvcjsKCiAgICBoYW5kbGVzWzBdID0gQ3JlYXRlRGV0YWNoZWRQcm9jZXNzKGFyZ3ZbMV0sIHN0cmVhbXMpOwogICAgaGFuZGxlc1sxXSA9IHN0cmVhbXNbMV0uaGFuZGxlOwogICAgaGFuZGxlc1syXSA9IHN0cmVhbXNbMl0uaGFuZGxlOwoKICAgIFdhaXRGb3JNdWx0aXBsZU9iamVjdHMoMywgaGFuZGxlcywgVFJVRSwgSU5GSU5JVEUpOwoKICAgIGZvciAoIGk9MDsgaTwzOyBpKyspCiAgICAgICAgQ2xvc2VIYW5kbGUoaGFuZGxlc1tpXSk7CgogICAgcmV0dXJuIDA7Cn0KCiNlbmRpZgo=