How to run a shell command in cocoa and get output? - objective-c

After repeated searching I have not found an elegant solution to this issue: how to run a shell command in obj-c and get it's output. I have read many questions regarding this, but they all fail to answer my question.
Some get the exit value ( Get result from shell script objective-c ) others only run the command ( Cocoa/ Objective-C Shell Command Line Execution ), and finally others have me write the output to a file ( Execute a terminal command from a Cocoa app ).
I really would like to avoid writing/reading a file as it not a very clean solution.
Is there no way to read the output directly in obj-c? If so how?

The code from "doshellscript" from the first link (Get result from shell script objective-c) actually does return an NSString with the output of the command. If it's not working for you, maybe the command is outputting over stderr rather than stdin? Have you tried this yet? The standard mechanism for running commands in Cocoa is NSTask, so definitely at least start there.

Look at the class PRHTask. It is a replacement of NSTask, with completion blocks. https://bitbucket.org/boredzo/prhtask
Extract from the header:
First, rather than having to set your own pipe for standard output and error, you can tell the task to accumulate the output for you, and retrieve it when the task completes.
Second, when the process exits, rather than posting an NSNotification, a PRHTask will call either of two blocks that you provide. You can set them both to the same block if you want.

If your task needs admin privileges, you might want to look at STPrivilegedTask.

Related

Giving unique names to GDB logging files in a script

I would like to log GDB command output to a log file.
This is done using the following command:
set logging file outfulfile.txt
But, instead of simple outfulfile.txt, I would like to give a unique name to the file; for example outfulfile-PID.txt. This is because I will have several processes simultaneously producing the output and I want each one to log to its own unique file.
How can I programmatically derive such a file name in a GDB script?
There area few ways.
One relatively simple way is to use gdb's "eval" command. It substitutes arguments like printf, and then executes the result as a gdb command. This is a new-ish command.
If you don't have "eval" you might still have Python scripting. In this case you can write a short (one line) Python script like:
(gdb) python gdb.execute('set logging file ' + .. your logic here ..)
If you don't have Python scripting, then your gdb is really old and you ought to upgrade. However you can still maybe accomplish what you want, just with some awful gyrations using "shell" and writing out a script that you then "source" back into gdb. Though this technique seems somewhat hard in this case.

gdb command file scripting: wait for breakpoint supported?

Im debugging quite a complex program with lots of queues, each having a relatively short timeout period set.
I cannot debug reliable in gdb's 'manual' command line mode, because timeouts are triggered when I type commands to slowly.
I don't like the idea of extending all the queue's timeouts, as this would make things really messy. (This sounds like the design itself is arguable, I know...)
I'd really like to use the gdb 'scripting' feature, but I haven't found a good tutorial for this.
Could anyone tell me if this is possible in a gdb "command file" script:
init some things (easy)
set a breakpoint
run programm
have the next command in script executed once the breakpoint is hit
So basically my question is: can I wait for a breakpoint inside a gdb command file script?
Answering my own question: I had success using hooks. My command file looks like this:
[initialization code]
define hook-stop
[commands to be executed at breakpoint]
end
set breakpoint pending on
b my_breakpoint_function
r

Call Perl Library from Objective-C cocoa

I have a Perl library i use to read some information from a file (closed format).
This library reads a file and returns an array of objects with the result.
Now i have to integrate that library (cannot implement it in cocoa right now) in a cocoa app. Basically call it and try to show the results in a list.
Is there some kind of bridge to call Perl libraries from ObjectiveC and get the results?
I've read something about using NSTask to call a perl script directly, and parse the result, but i wonder if it could be possible to do that call directly.
best regards.
You are perfectly right: NSTask is on Cocoa (not Cocoa-Touch) the right class for you. You can launch any subprocess, considering that this subprocess will inherit the environment from you main task (but of course you can apply different settings, e.g. the run directory).
The advantage with respect to "system()" is that NSTask "launch" method is non blocking so you can use it for long aysnchronous jobs (and be notified when it is over).
For the specific case of perl, just run the perl script as in command line: "/usr/bin/perl ..."
Finally you can make a try with PerlObjCBridge (link: PerlObjCBridge.pm man page) for a sort of interprocess communication between Objective-C objects and perl.
If you want a bridge, take a look at PerlObjCBridge. If you just want to call the script, I believe you can just use system(). Something like this:
system( [scriptCallNSString UTF8String] );

strange behavior

I wrote simple script test
echo hello #<-- inside test
if I press one time enter after hello, my script will run, if I don't press - it will not, if two times I'll receive my hello and + command was not found, can somebody please explain me this behavior thanks in advance
This is not a part of the code, this is actual code
and I run it on C-Shell, via editor of Windows
command:
source ./test
Some points:
You should not ask questions tagged with both the [csh] and [bash] tags - these are completely different programs and implement completely different script programming languages
You should never name a script (or any other program) test, as this is the name of a built-in feature of bash
Post the actual code you are asking about, without annotations and show how you run it.
I have tried a similar case. I wrote a script like yours, saved it using Windows Notepad (with CRLF line terminators) and run in bash with the same effect as yours in csh. The problem is bash (so csh as well) does not understand Windows' 2-byte line terminators, which are interpreted as commands, which obviously do not exist.
The solution is: change your editor or configure your current editor to use unix line terminators.
You can try for example Notepad++. Remember to change the line terminators to LF.

Easiest way to run shell script objective-c

I am a objective-c newbe and am wondering how to run a shell script in objective-c easiest way possible. I don't care about any of the output. I have tried system(), exec() and execl() and an NSTask. Those methods don't work for some reason... This is the shell script I am trying to run:
"mount_webdav http://idisk.mac.com/idisk_username/ /Volumes/idisk_username"
(Basically mounting my iDisk). Also, no password-boxes or any indication of it working shows.
It will work in applescript, and I have created the mount-point directory. None of the methods above do anything at all, or crash the application for some weird reason.
NSTask supplies everything you need. This should work:
NSArray *args=[NSArray arrayWithObjects:#"http://idisk.mac.com/idisk_username/",#"/Volumes/idisk_username",nil];
NSTask *mountTask=[[NSTask alloc] init];
[mountTask setLaunchPath:#"/sbin/mount_webdav"];
[mountTask launch];
Test all the complete command path and args from the command line first. I haven't used mount_webdav but I think it requires more args than you supplied.
Don't use shell scripts when you can help it. They're a good way to introduce serious bugs when you parameterize the script (e.g., mount_webdav %# %#).
Instead, use either NSTask, fork/exec directly, or (in Python) the subprocess module. You'll pass the three arguments as an array, rather than as a single string.
NSTask would be the way to do this in Cocoa. You might want to go over your code again, read up on the documentation for it (also look at the sample code there), and post specific questions about its usage here if you run into problems.