@@ -15,19 +15,25 @@ */ #include "config.h" #include +#include #ifndef _WIN32 # include # include #endif + +#ifdef __MACH__ +# include +#endif #import "OFProcess.h" #import "OFString.h" #import "OFArray.h" +#import "OFDictionary.h" #import "OFInitializationFailedException.h" #import "OFReadFailedException.h" #import "OFWriteFailedException.h" @@ -34,10 +40,14 @@ #ifdef _WIN32 # include #endif #import "autorelease.h" + +#ifndef __MACH__ +extern char **environ; +#endif @implementation OFProcess + (instancetype)processWithProgram: (OFString*)program { return [[[self alloc] initWithProgram: program] autorelease]; @@ -56,29 +66,53 @@ { return [[[self alloc] initWithProgram: program programName: programName arguments: arguments] autorelease]; } + ++ (instancetype)processWithProgram: (OFString*)program + programName: (OFString*)programName + arguments: (OFArray*)arguments + environment: (OFDictionary*)environment +{ + return [[[self alloc] initWithProgram: program + programName: programName + arguments: arguments + environment: environment] autorelease]; +} + +- initWithProgram: (OFString*)program +{ + return [self initWithProgram: program + programName: program + arguments: nil + environment: nil]; +} - initWithProgram: (OFString*)program + arguments: (OFArray*)arguments { return [self initWithProgram: program programName: program - arguments: nil]; + arguments: arguments + environment: nil]; } - initWithProgram: (OFString*)program + programName: (OFString*)programName arguments: (OFArray*)arguments { return [self initWithProgram: program programName: program - arguments: arguments]; + arguments: arguments + environment: nil]; } - initWithProgram: (OFString*)program programName: (OFString*)programName arguments: (OFArray*)arguments + environment: (OFDictionary*)environment { self = [super init]; @try { #ifndef _WIN32 @@ -103,10 +137,13 @@ cStringUsingEncoding: OF_STRING_ENCODING_NATIVE]; argv[i + 1] = NULL; + if (environment != nil) + [self OF_setEnvironment: environment]; + close(readPipe[0]); close(writePipe[1]); dup2(writePipe[0], 0); dup2(readPipe[1], 1); execvp([program cStringUsingEncoding: @@ -222,10 +259,55 @@ @throw e; } return self; } + +- (void)OF_setEnvironment: (OFDictionary*)environment +{ + OFEnumerator *keyEnumerator, *objectEnumerator; + char **envp; + size_t i, count; + + count = [environment count]; + envp = [self allocMemoryWithSize: sizeof(char*) + count: count + 1]; + + keyEnumerator = [environment keyEnumerator]; + objectEnumerator = [environment objectEnumerator]; + + for (i = 0; i < count; i++) { + OFString *key; + OFString *object; + size_t keyLen, objectLen; + + key = [keyEnumerator nextObject]; + object = [objectEnumerator nextObject]; + + keyLen = [key lengthOfBytesUsingEncoding: + OF_STRING_ENCODING_NATIVE]; + objectLen = [object lengthOfBytesUsingEncoding: + OF_STRING_ENCODING_NATIVE]; + + envp[i] = [self allocMemoryWithSize: keyLen + objectLen + 2]; + + memcpy(envp[i], [key cStringUsingEncoding: + OF_STRING_ENCODING_NATIVE], keyLen); + envp[i][keyLen] = '='; + memcpy(envp[i] + keyLen + 1, [object cStringUsingEncoding: + OF_STRING_ENCODING_NATIVE], objectLen); + envp[i][keyLen + objectLen + 1] = '\0'; + } + + envp[i] = NULL; + +#ifdef __MACH__ + *_NSGetEnviron() = envp; +#else + environ = envp; +#endif +} - (BOOL)lowlevelIsAtEndOfStream { #ifndef _WIN32 if (readPipe[0] == -1)