Returning values from terminal

I'm opening a different thread to a question that was asked about a year ago. I'm trying to get the output of "which" so that I can automatically find programs for the user. I've used the code that was provided in that thread which is:

 func launch(tool: URL, arguments: [String], completionHandler: @escaping (Int32, Data) -> Void) throws {

        let group = DispatchGroup()

        let pipe = Pipe()

        var standardOutData = Data()



        group.enter()

        let proc = Process()

        proc.executableURL = tool

        proc.arguments = arguments

        proc.standardOutput = pipe.fileHandleForWriting

        proc.terminationHandler = { _ in

            proc.terminationHandler = nil

            group.leave()

        }



        group.enter()

        DispatchQueue.global().async {

            // Doing long-running synchronous I/O on a global concurrent queue block

            // is less than ideal, but I’ve convinced myself that it’s acceptable

            // given the target ‘market’ for this code.



            let data = pipe.fileHandleForReading.readDataToEndOfFile()

            pipe.fileHandleForReading.closeFile()

            DispatchQueue.main.async {

                standardOutData = data

                group.leave()

            }

        }



        group.notify(queue: .main) {

            completionHandler(proc.terminationStatus, standardOutData)

        }



        try proc.run()



        // We have to close our reference to the write side of the pipe so that the

        // termination of the child process triggers EOF on the read side.



        pipe.fileHandleForWriting.closeFile()

    }

it works fine for all of the normal command line routines but not for custom ones such as avr-gcc or any other that is installed via homebrew. I can use "which avr-gcc" in terminal and it shows the path just fine but in my app it returns nothing where as if I search for the path of something like ls in my app it returns it just fine. What could be the cause of this?

Replies

Running a child process with pipes connected to stdin and stdout is surprisingly complex. It looks like you’re using an old version of my code (from here). That code has it’s problems, and I just posted a new, much improved version. See Running a Child Process with Standard Input and Output.

Also, if your curious about some of the issues I encountered, check out Whither FileHandle?.

Be warned that this is not the end of the story. Some programs rely on environmental factors that aren’t covered by this simplistic wrapper. So, experiment with this new code and, if you still have problems, post an update here with the details.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yeah, it still does the same thing with "which". It returns empty for homebrew apps but not the standard ones. I had already resigned myself to making people just find the apps themselves and put a note to do a search in the terminal for them. It shouldn't be necessary anyway. My app is just a UI wrapper for a command line tool itself so it's just saving people who probably already know it well enough some time. I'll work on it from time to time to see if I can figure out the problem but I'm not going to beat myself over the head about it. This was supposed to just be a quick little project to make life a little easier on myself and some others. It's weird though. I'm able to do just about everything from terminal commands with my app like pushd to change directory which is sometimes needed and the apps run fine, sometimes with like 10 arguments. It's only "which" that gives me any problems.

Thanks for the help

Yeah, it still does the same thing with which. It returns empty for homebrew apps but not the standard ones.

OK. This is probably something to do with your shell path setup.

I can use which avr-gcc in terminal and it shows the path just fine

That’s running the version of which that’s built in to your shell. If, in Terminal, you explicitly run the which tool, what do you see. That is:

% /usr/bin/which avr-gcc

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"