0

I have virtually no programing experience beyond shell scripting, but I'm in a situation where I need to call a binary with launchd and because of security changes in Catilina, it looks as though it cannot be a AppleScript .app, Automator .app, or a Platypus .app. All three of those call some sort of GUI element and none will work as at startup.

I've cobbled together a snippet of code that compiles and works to call the script I need. I've bundled it a .app, signed it, and it works. But I'd very much like to call the script relative to the binary.

How can I call the equivalent of

[task setArguments:@[ @"../Resources/script" ]];

instead of

[task setArguments:@[ @"/Full/Path/To/script" ]];

Below is the entirety of the main.m

#import <Foundation/Foundation.h>
enter code here
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
       NSTask *task = [[NSTask alloc] init];
        [task setLaunchPath:@"/bin/zsh"];
        [task setArguments:@[ @"/Full/Path/To/script" ]];
        [task launch];
    }
    return 0;
}

As an aside, I know there are much better ways to do this, but my goal os not to have an award winning app, but to simply bridge a specific problem. Many thanks.

peet
  • 5
  • 2

2 Answers2

0

You get the current directory with NSFileManager

NSString* path = [[NSFileManager defaultManager] currentDirectoryPath];

The first argument in argv is the path to the binary

Either

NSString *path = [NSString stringWithUTF8String:argv[0]];

or

NSString *path = [[NSProcessInfo processInfo] arguments][0];
vadian
  • 274,689
  • 30
  • 353
  • 361
  • thank you, but this seems to just get the current working directory of the binary. I really need to the binary's path on the file system. Any ideas there? – peet Feb 25 '20 at 23:27
0

You should use NSBundle for this. In particular, you should use:

[[NSBundle mainBundle] pathForResource:@"script" ofType:nil]

as in:

[task setArguments:@[ [[NSBundle mainBundle] pathForResource:@"script" ofType:nil] ]];
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • This works if the target is a Cocoa **application** but not for a command line interface (binary). – vadian Feb 25 '20 at 22:39
  • @vadian And OP said that's what they're using. And even if it weren't, using `[[NSBundle mainBundle] executablePath]` would still be the right way to find a file relative to the program. There's no guarantee about what the current directory path is, so that's not useful. – Ken Thomases Feb 25 '20 at 23:10