Search code examples
javaobjective-cnstaskalice

I can't see the output of NSTask - objective-c JAVA


Here is my code:

NSTask *setupTask = [NSTask new];
[setupTask setLaunchPath:@"/bin/sh"];
[setupTask setArguments:[NSArray arrayWithObject:@"/applications/jarvis/brain/server.sh"]];
[setupTask setCurrentDirectoryPath:@"/"];
NSPipe *outputPipeSetup = [NSPipe pipe];
[setupTask setStandardInput:[NSPipe pipe]];
[setupTask setStandardOutput:outputPipeSetup];
[setupTask launch];

NSTask *aliceTask = [NSTask new];
[aliceTask setLaunchPath:@"/usr/bin/java"];
[aliceTask setArguments:[NSArray arrayWithObjects:@"-classpath", @"/applications/jarvis/brain/", @"-Xms64m", @"-Xmx128m", @"org.alicebot.server.net.AliceServer", nil]];

 NSPipe *aliceInputPipe = [NSPipe pipe];
 [aliceTask setStandardInput:aliceInputPipe];
 NSPipe *aliceOutputPipe = [NSPipe pipe];
 [aliceTask setStandardOutput:aliceOutputPipe];

 [aliceTask launch];

NSMutableString *outputString = [NSMutableString string];
while ([outputString rangeOfString:@"Jarvis>"].location == NSNotFound) {
    [outputString appendString:[[[NSString alloc] initWithData:[[aliceOutputPipe fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding] autorelease]];
}

BUT, outputString returns nothing and it get's stuck in the while loop. Here is the server.sh file:

echo Starting Jarvis Program D.
ALICE_HOME=.
SERVLET_LIB=lib/servlet.jar
ALICE_LIB=lib/aliceserver.jar
JS_LIB=lib/js.jar

# Set SQL_LIB to the location of your database driver.
SQL_LIB=lib/mysql_comp.jar

# These are for Jetty; you will want to change these if you are using a different http server.
 HTTP_SERVER_LIBS=lib/org.mortbay.jetty.jar

 PROGRAMD_CLASSPATH=$SERVLET_LIB:$ALICE_LIB:$JS_LIB:$SQL_LIB:$HTTP_SERVER_LIBS
 java -classpath $PROGRAMD_CLASSPATH -Xms64m -Xmx128m org.alicebot.server.net.AliceServer $1

Solution

  • You may try to process the server.sh output using just one NSTask that calls: sh -c 'source server.sh | sed "/Jarvis>/q"' (cf. shstring). In this simplified code example server.sh (shfile) just contains a single cat(1) command to write the contents of test.file to stdout. Maybe you can just add the java command that is called from Objective-C to shstring as well?

    #import <Foundation/Foundation.h>
    
    /*
    
    See:
    http://stackoverflow.com/questions/3505942/i-cant-see-the-output-of-nstask-objective-c-java
    
    compile with:
    gcc -Wall -O3 -x objective-c -fobjc-exceptions -framework Foundation -o test test.c
    
    ./test
    
    # create test.file
    n=50
    jot -b 'line' $n | nl -w 10 > test.file
    echo "Jarvis>" | nl -w 10 -v $((n+1)) >> test.file
    jot -b 'line' 19 | nl -w 10 -v $((n+2)) >> test.file
    
    ls -lh test.file
    tail -n 100 test.file
    
    # create server.sh
    echo '
    cat test.file
    ' > server.sh
    
    sh server.sh
    
    ./test
    
    */
    
    
    int main(int argc, const char *argv[])
    {
    
        NSAutoreleasePool *pool =  [[NSAutoreleasePool alloc] init];
        NSString *shfile = @"server.sh";
    
        NSString *shstring = [NSString stringWithFormat:
                 @"%@ %@ %@", 
                 @"source", 
                 shfile, 
                 @"| /usr/bin/sed '/Jarvis>/q'"
        ];
    
        NSTask *sh = [NSTask new];
        NSPipe *pipe = [NSPipe new];
        [sh setLaunchPath:@"/bin/sh"];
        [sh setArguments:[NSArray arrayWithObjects: @"-c", shstring, nil ]];
        [sh setCurrentDirectoryPath:@"."];
        //[sh setStandardInput:[NSFileHandle fileHandleWithNullDevice]];
        [sh setStandardError:[NSFileHandle fileHandleWithNullDevice]];
        [sh setStandardOutput:pipe];
        [sh launch];
    
        NSData *data = [[[sh standardOutput] fileHandleForReading] readDataToEndOfFile];
        NSString *string = [[[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding] autorelease];
    
        NSLog(@"\n\n%@\n", string);
    
        [pool release];
    
        return 0;
    
    }