How to execute shell-command "ping" and get result into string in Objective-C/Cocoa? - cocoa

I tried this code
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/usr/bin/ping"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: #"-c", #"3",#"stackoverfow.com", nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (#"ping returned:\n%#", string);
[string release];
[task release];
And got this
2011-10-21 17:34:42.805 pintTest[8819:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'launch path not accessible'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8acab286 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff89463d5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff8acab0ba +[NSException raise:format:arguments:] + 106
3 CoreFoundation 0x00007fff8acab044 +[NSException raise:format:] + 116
4 Foundation 0x00007fff8fc6c2c8 -[NSConcreteTask launchWithDictionary:] + 470
5 pintTest 0x0000000100000de0 main + 400
6 pintTest 0x0000000100000c44 start + 52
7 ??? 0x0000000000000001 0x0 + 1
)
terminate called throwing an exceptionsharedlibrary apply-load-rules all
Current language: auto; currently objective-c

Try replacing:
[task setLaunchPath: #"/usr/bin/ping"];
with
[task setLaunchPath: #"/sbin/ping"];
since that’s where ping is located.

Related

NSProcessInfo returns different PATH than "echo $PATH"

I am trying to programatically figure out whether there is a specific binary in the system PATH. To get the environment I used both
NSString* path = [[[NSProcessInfo processInfo] environment] objectForKey:#"PATH"];
and
NSString* path2 = [NSString stringWithUTF8String: getenv("PATH")];
both yielding the same result, in both cases different then echo $PATH in console. Both path and path2 does not contain paths set via /etc/paths.d, so the question is how to get the the environment PATH as returned from console programatically?
NSProcessInfo will just access information about current process. For example below i am executing the same echo $PATH command in cocoa and am getting the same output which NSProcessInfo is displaying. So in the terminal when you execute the same command. You will get different ouput. Because it is showing the path of current process in terminal. If you want to see the same output of both you can execute this command in terminal launchctl getenv PATH which will be equivalent to [[[NSProcessInfo processInfo] environment] objectForKey:#"PATH"];
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/bash"];
[task setArguments:[NSArray arrayWithObjects: #"-c", #"echo $PATH",nil]];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *response = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"%#",response);

Forcing Python to run in 64 mode from a NSTask subprocess

What is a method that forces python to run in 64 mode from a NSTask?
Update: As per Ned's suggestion I tried referencing Python2.7 directly with objective c and that worked. Changed #"/usr/bin/python" to #"/usr/bin/python2.7". The new code is at the bottom of the question.
I have a 64 bit system. When run from terminal python runs in 64 bit.
When I run a plain shell from a NSTask running /usr/bin/uname -m it returns x86_64.
I've tried using arch but the shell running python is still in 32 bit mode.
Example method
-(void) runPython64BitScriptViaArchWithPath:(NSString*)path {
NSTask* task = [[NSTask alloc] init];
task.launchPath = #"/usr/bin/arch" ;
task.arguments = [NSArray arrayWithObjects: #"-x86_64", #"/usr/bin/python", path, nil];
[task setStandardInput:[NSPipe pipe]] ;
NSPipe *stdOutPipe = nil;
stdOutPipe = [NSPipe pipe];
[task setStandardOutput:stdOutPipe];
NSPipe* stdErrPipe = nil;
stdErrPipe = [NSPipe pipe];
[task setStandardError: stdErrPipe];
NSLog(#"%#", [task arguments]) ;
[task launch] ;
NSData* data = [[stdOutPipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
NSInteger exitCode = task.terminationStatus;
if (exitCode != 0)
{
NSLog(#"Error!");
NSData *error = [[stdErrPipe fileHandleForReading] readDataToEndOfFile] ;
NSLog(#"Exit code : %ld", (long)exitCode) ;
NSString *result = [[NSString alloc] initWithBytes: error.bytes length:error.length encoding: NSUTF8StringEncoding] ;
NSLog(#"%#",result);
[result release];
} else {
NSString *result = [[NSString alloc] initWithBytes: data.bytes length:data.length encoding: NSUTF8StringEncoding] ;
NSLog(#"%#",result) ;
[result release];
}
[task release] ;
}
an example python script that works if run from terminal
#!/usr/bin/env python
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'social_shields.settings'
try:
import hosts.models
shield = hosts.models.Shield.objects.all()[0]
shield.active = True
shield.save()
except Exception as exception:
import struct
print 'Bits : %s' % ( 8 * struct.calcsize("P"))
print exception
example log
2013-07-04 16:10:31.600 socialshield[88688:303] onShieldDown
2013-07-04 16:10:31.607 socialshield[88688:303] x86_64
2013-07-04 16:10:31.607 socialshield[88688:303] (
"-x86_64",
"/usr/bin/python",
"/source/social_shields/social_shields/shield_down.py"
)
2013-07-04 16:10:31.933 socialshield[88688:303] Bits : 32
Error loading MySQLdb module: dlopen(/Library/Python/2.7/site-packages/_mysql.so, 2): no suitable image found. Did find:
/Library/Python/2.7/site-packages/_mysql.so: mach-o, but wrong architecture
new code that works after applying Ned's suggestion :-)
-(void) runPython64BitScriptViaArchWithPath:(NSString*)path {
NSTask* task = [[NSTask alloc] init];
task.launchPath = #"/usr/bin/arch" ;
task.arguments = [NSArray arrayWithObjects: #"-x86_64", #"/usr/bin/python2.7", path, nil];
[task setStandardInput:[NSPipe pipe]] ;
NSPipe *stdOutPipe = nil;
stdOutPipe = [NSPipe pipe];
[task setStandardOutput:stdOutPipe];
NSPipe* stdErrPipe = nil;
stdErrPipe = [NSPipe pipe];
[task setStandardError: stdErrPipe];
NSLog(#"%#", [task arguments]) ;
[task launch] ;
NSData* data = [[stdOutPipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
NSInteger exitCode = task.terminationStatus;
if (exitCode != 0)
{
NSLog(#"Error!");
NSData *error = [[stdErrPipe fileHandleForReading] readDataToEndOfFile] ;
NSLog(#"Exit code : %ld", (long)exitCode) ;
NSString *result = [[NSString alloc] initWithBytes: error.bytes length:error.length encoding: NSUTF8StringEncoding] ;
NSLog(#"%#",result);
[result release];
} else {
NSString *result = [[NSString alloc] initWithBytes: data.bytes length:data.length encoding: NSUTF8StringEncoding] ;
NSLog(#"%#",result) ;
[result release];
}
[task release] ;
}
I assume you have verified that /Library/Python/2.7/site-packages/_mysql.so is 64-bit and that you are really using the same Python in both cases. On OS X 10.6 and later systems, /usr/bin/python is actually a wrapper executable that determines which version of Python and which architecture (32-bit or 64-bit) to run; see man 1 python for details. Try executing /usr/bin/python2.7 directly. That should default to 64-bit. You can also check whether Python is running in 32- or 64-bit mode by using this documented test:
import sys; print(sys.maxsize > 2**32)

Append data to an existing file in new line cocoa

I'm developing a Cocoa application for Mac. I have to append data of a file to an existing file in new line. I am trying to do this by following code:
NSData * theData = [NSData dataWithContentsOfFile: #"~/Desktop/test/new.rtf"
options: NSMappedRead
error: &error];
NSFileHandle *output = [NSFileHandle fileHandleForWritingAtPath:#"~/Desktop/test/test.rtf"];
[output seekToEndOfFile];
[output writeData:theData];
But this code is not working. This code is doing nothing. Neither giving any error nor writing data of file new.rtf to test.rtf. Any idea how can I append data of file new.rtf to test.rtf in new line??
NSString *readFile = [#"~/Desktop/test/new.rtf" stringByExpandingTildeInPath];
NSString *writeFile = [#"~/Desktop/test/test.rtf" stringByExpandingTildeInPath];
NSData * theData = [NSData dataWithContentsOfFile:readFile
options:NSMappedRead
error:NULL];
NSFileHandle *output = [NSFileHandle fileHandleForUpdatingAtPath:writeFile];
[output seekToEndOfFile];
[output writeData:theData];
[output closeFile];

NSTask and arguments when running command line tools

How would I pass arguments (host in this case) to NSTask in this code? It does not accept the host NSString. If I pass the host value with the ping, for e.g..
[NSArray arrayWithObjects:#"-c",#"ping -c 5 www.google.com",nil]
then it works. But it won't take the host argument separately. Thanks for the help in advance.
task = [[NSTask alloc] init];
[pipe release];
pipe = [[NSPipe alloc] init];
[task setStandardInput: [NSPipe pipe]];
[task setLaunchPath:#"/bin/bash"];
NSArray *args = [NSArray arrayWithObjects:#"-c",#"ping -c 5",host,nil];
[task setArguments:args];
[task setStandardOutput:pipe];
NSFileHandle *fh = [pipe fileHandleForReading];
Use stringWithFormat method of NSString class
task = [[NSTask alloc] init];
[pipe release];
pipe = [[NSPipe alloc] init];
[task setStandardInput: [NSPipe pipe]];
[task setLaunchPath:#"path"];
NSArray *args = [NSArray arrayWithObjects:#"-c",[NSString stringWithFormat: #"%# %# %# %#",#"ping",#"-c",#"5",host],nil];
[task setArguments:args];
[task setStandardOutput:pipe];
NSFileHandle *fh = [pipe fileHandleForReading];
Your arguments are not correct. First of all, you should set the launchpath to /bin/ping, or wherever the task is located, then the arguments should be an array of the arguments you would normally enter on the command line, but then seperated by spaces there..
Please take a look at this tutorial Wrapping UNIX commands for more information on how to do this properly.
NSMutableArray *args = [NSMutableArray array];
NSArray *args = [NSArray arrayWithObjects:#"-c", #"\"ping -c 5", host, #"\"",nil]
[task setArguments:args];
Bash -c needs to take your command in quotes.

Mind boggling QTMovie export crash

Hey guys... I'm at my wits end here. I've been focusing on this issue for the last 3 days it seems, and I'm still no closer to solving it. I've got a queue of videos that I'm converting one after the other in a background thread. Most of the time it works as expected, but every so often, I get a weird crash, always at the same point. I can't for the life of me figure out why it's happening. I've got garbage collection enabled. Here is my conversion code.
Here is the stack trace.
Edit: After a bit more debugging, I am back to the conclusion that maybe it is garbage collector related. If I place the following line just before the line that converts the video, I get a drastic increase in the amount of these errors that I see...
[[NSGarbageCollector defaultCollector] collectExhaustively];
NSInvalidArgumentException
-[NSPathStore2 objectForKey:]: unrecognized selector sent to instance 0x1073570
(
0 CoreFoundation 0x92fc16ba __raiseError + 410
1 libobjc.A.dylib 0x901b4509 objc_exception_throw + 56
2 CoreFoundation 0x9300e90b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x92f67c36 ___forwarding___ + 950
4 CoreFoundation 0x92f67802 _CF_forwarding_prep_0 + 50
5 QTKit 0x903d3280 MovieProgressProc + 62
6 QuickTime 0x95a66062 convertFileProgress + 212
7 QuickTime3GPP 0x1e7bcaa2 Spit3GP2_Progress + 180
8 QuickTime3GPP 0x1e7c01d8 Spit3GP2_FromProceduresToDataRef + 3438
9 CarbonCore 0x90b0d054 _ZL38CallComponentFunctionCommonWithStoragePPcP19ComponentParametersPFlvEm + 54
10 QuickTime3GPP 0x1e7be33d Spit3GP2_ComponentDispatch + 129
11 CarbonCore 0x90b057c9 CallComponentDispatch + 29
12 QuickTime 0x95befb97 MovieExportFromProceduresToDataRef + 49
13 QuickTime3GPP 0x1e7bdf84 Spit3GP2_ToDataRef + 1987
14 CarbonCore 0x90b1865d callComponentStorage_4444444 + 63
15 CarbonCore 0x90b0d054 _ZL38CallComponentFunctionCommonWithStoragePPcP19ComponentParametersPFlvEm + 54
16 QuickTime3GPP 0x1e7be33d Spit3GP2_ComponentDispatch + 129
17 CarbonCore 0x90b057c9 CallComponentDispatch + 29
18 QuickTime 0x95befbe2 MovieExportToDataRef + 73
19 QuickTime 0x95a6e9bb ConvertMovieToDataRef_priv + 1690
20 QuickTime 0x95bdc591 ConvertMovieToDataRef + 71
21 QTKit 0x903e0954 -[QTMovie_QuickTime writeToDataReference:withAttributes:error:] + 2692
22 QTKit 0x903c5110 -[QTMovie_QuickTime writeToFile:withAttributes:error:] + 111
23 Mevee 0x0005871d -[ConversionQueue convertVideo:] + 509
24 Mevee 0x00058341 -[ConversionQueue startConvertingItems] + 145
25 Foundation 0x9520fbf0 -[NSThread main] + 45
26 Foundation 0x9520fba0 __NSThread__main__ + 1499
27 libSystem.B.dylib 0x9475a85d _pthread_start + 345
28 libSystem.B.dylib 0x9475a6e2 thread_start + 34
)
- (id) init
{
if(!(self = [super init])) return self;
convertingIndex = 0;
conversionPaths = [[NSMutableArray alloc] init];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/2 Fast 2 Furious/2 Fast 2 Furious.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/101 Dalmations/101 Dalmations.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/300/300.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/1408/1408.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/A Few Good Men/A Few Good Men.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/A Goofy Movie/A Goofy Movie.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/A Single Man/A Single Man.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/A View to a Kill/A View to a Kill.mp4"];
[conversionPaths addObject:#"/Users/Morgan/Desktop/Convertable Media/Movies/Across the Universe/Across the Universe.mp4"];
backgroundThread = [[NSThread alloc] initWithTarget:self selector:#selector(startConvertingItems) object:nil];
[backgroundThread start];
return self;
}
- (void) startProcessingQueue
{
}
- (void) startConvertingItems
{
NSInteger iterations = 0;
while(iterations < 100)
{
NSString* nextPath = [conversionPaths objectAtIndex:convertingIndex];
NSLog(#"ITERATION %d", iterations);
[self convertVideo:nextPath];
convertingIndex += 1;
if(convertingIndex >= [conversionPaths count])
convertingIndex = 0;
iterations += 1;
}
}
- (void) openMovieOnMainThread:(NSString*)path
{
NSError* error = nil;
movie = [[QTMovie alloc] initWithFile:path error:&error];
if(movie == nil || error != nil || ![movie detachFromCurrentThread])
movie = nil;
}
- (void) closeMovieOnMainThread
{
//[movie attachToCurrentThread];
//[movie release];
}
- (BOOL) convertVideo: (NSString*)path
{
[self performSelectorOnMainThread:#selector(openMovieOnMainThread:) withObject:path waitUntilDone:YES];
if(movie == nil) {
NSLog(#"ERROR OPENING MOVIE");
return NO;
}
[QTMovie enterQTKitOnThreadDisablingThreadSafetyProtection];
[movie attachToCurrentThread];
[movie setDelegate:self];
NSString* tempItemPath = #"/Users/Morgan/Desktop/test.mp4";
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], QTMovieExport,
[NSNumber numberWithLong:'3gpp'], QTMovieExportType,
nil];
NSError* error = nil;
if(![movie writeToFile:tempItemPath withAttributes:attrs error:&error]) {
NSLog(#"ERROR CONVERTING MOVIE");
return NO;
}
[movie invalidate];
[movie detachFromCurrentThread];
[QTMovie exitQTKitOnThread];
[self performSelectorOnMainThread:#selector(closeMovieOnMainThread) withObject:nil waitUntilDone:YES];
return YES;
}
- (BOOL)movie:(QTMovie *)aMovie shouldContinueOperation:(NSString *)op withPhase:(QTMovieOperationPhase)phase atPercent:(NSNumber *)percent withAttributes:(NSDictionary *)attributes
{
switch (phase)
{
case QTMovieOperationBeginPhase:
NSLog(#"Conversion started");
break;
case QTMovieOperationUpdatePercentPhase:
NSLog(#"Conversion progress: %f", [percent floatValue]);
break;
case QTMovieOperationEndPhase:
NSLog(#"Conversion finished.");
break;
}
return YES;
}
Ahhh... I found out it was the stupid garbage collector. Reworked my app to work with reference counting rather than garbage collection, and smooth sailing. Has anyone else come across similar garbage collection bugs? I had a strong reference to a root object for my movie file, so I don't think that was the problem.

Resources