forked from NMSSH/NMSSH
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for executing shell commands
- Loading branch information
Lejdborg
committed
Jun 30, 2012
1 parent
60310f7
commit ffd6c96
Showing
10 changed files
with
214 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
#import "NMSSHSession.h" | ||
#import "NMSSHSession.h" | ||
#import "NMSSHChannel.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,45 @@ | ||
// | ||
// NMSSHChannel.h | ||
// NMSSH | ||
// | ||
// Created by Christoffer Lejdborg on 2012-06-30. | ||
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
@class NMSSHSession; | ||
|
||
enum { | ||
NMSSHChannelExecutionError, | ||
NMSSHChannelExecutionResponseError | ||
}; | ||
|
||
/** | ||
* NMSSHChannel provides functionality to work with SSH shells and SCP. | ||
*/ | ||
@interface NMSSHChannel : NSObject | ||
|
||
/** A valid NMSSHSession instance */ | ||
@property (nonatomic, readonly) NMSSHSession *session; | ||
|
||
/** The last response from a shell command execution */ | ||
@property (nonatomic, readonly) NSString *lastResponse; | ||
|
||
/** | ||
* Create a new NMSSHChannel instance and open a channel on the provided | ||
* session. | ||
* | ||
* aSession needs to be a valid, connected, NMSSHSession instance! | ||
* | ||
* @returns New NMSSHChannel instance | ||
*/ | ||
- (id)initWithSession:(NMSSHSession *)aSession; | ||
|
||
/** | ||
* Close and cleanup the channel | ||
*/ | ||
- (void)close; | ||
|
||
/** | ||
* Execute a shell command on the server. | ||
* | ||
* If an error occurs, it will return nil and populate the error object. | ||
* | ||
* @returns Shell command response | ||
*/ | ||
- (NSString *)execute:(NSString *)command error:(NSError **)error; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,92 @@ | ||
// | ||
// NMSSHChannel.m | ||
// NMSSH | ||
// | ||
// Created by Christoffer Lejdborg on 2012-06-30. | ||
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. | ||
// | ||
|
||
#import "NMSSHChannel.h" | ||
#import "NMSSHSession.h" | ||
|
||
#import "libssh2.h" | ||
|
||
@interface NMSSHChannel () { | ||
LIBSSH2_CHANNEL *channel; | ||
} | ||
@end | ||
|
||
@implementation NMSSHChannel | ||
@synthesize session, lastResponse; | ||
|
||
// ----------------------------------------------------------------------------- | ||
// PUBLIC SETUP API | ||
// ----------------------------------------------------------------------------- | ||
|
||
- (id)initWithSession:(NMSSHSession *)aSession { | ||
if ((self = [super init])) { | ||
session = aSession; | ||
|
||
// Make sure we were provided a valid session | ||
if (![session isKindOfClass:[NMSSHSession class]]) { | ||
return nil; | ||
} | ||
|
||
// Open up the channel | ||
if (!(channel = libssh2_channel_open_session([session rawSession]))) { | ||
NSLog(@"NMSSH: Unable to open a session"); | ||
return nil; | ||
} | ||
} | ||
|
||
return self; | ||
} | ||
|
||
- (void)close { | ||
if (channel) { | ||
libssh2_channel_close(channel); | ||
libssh2_channel_free(channel); | ||
channel = nil; | ||
} | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
// PUBLIC SHELL EXECUTION API | ||
// ----------------------------------------------------------------------------- | ||
|
||
- (NSString *)execute:(NSString *)command error:(NSError **)error { | ||
lastResponse = nil; | ||
|
||
// In case of error... | ||
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:command | ||
forKey:@"command"]; | ||
|
||
// Try executing command | ||
int rc = libssh2_channel_exec(channel, [command UTF8String]); | ||
if (rc) { | ||
*error = [NSError errorWithDomain:@"NMSSH" | ||
code:NMSSHChannelExecutionError | ||
userInfo:userInfo]; | ||
|
||
NSLog(@"NMSSH: Error executing command"); | ||
return nil; | ||
} | ||
|
||
// Fetch response from output buffer | ||
for (;;) { | ||
int rc; | ||
do { | ||
char buffer[0x4000]; | ||
rc = libssh2_channel_read(channel, buffer, sizeof(buffer)); | ||
|
||
if (rc != LIBSSH2_ERROR_EAGAIN) { | ||
lastResponse = [NSString stringWithCString:buffer | ||
encoding:NSUTF8StringEncoding]; | ||
return lastResponse; | ||
} | ||
} | ||
while (rc > 0); | ||
} | ||
|
||
// If we've got this far, it means fetching execution response failed | ||
*error = [NSError errorWithDomain:@"NMSSH" | ||
code:NMSSHChannelExecutionResponseError | ||
userInfo:userInfo]; | ||
|
||
NSLog(@"NMSSH: Error fetching response from command"); | ||
return nil; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,4 @@ | ||
// | ||
// NMSSHChannelTests.h | ||
// NMSSH | ||
// | ||
// Created by Christoffer Lejdborg on 2012-06-30. | ||
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. | ||
// | ||
|
||
#import <SenTestingKit/SenTestingKit.h> | ||
|
||
@interface NMSSHChannelTests : SenTestCase | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,63 @@ | ||
// | ||
// NMSSHChannelTests.m | ||
// NMSSH | ||
// | ||
// Created by Christoffer Lejdborg on 2012-06-30. | ||
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. | ||
// | ||
|
||
#import "NMSSHChannelTests.h" | ||
#import "ConfigHelper.h" | ||
|
||
#import <NMSSH/NMSSH.h> | ||
|
||
@interface NMSSHChannelTests () { | ||
NSDictionary *settings; | ||
|
||
NMSSHChannel *channel; | ||
NMSSHSession *session; | ||
} | ||
@end | ||
|
||
@implementation NMSSHChannelTests | ||
|
||
// ----------------------------------------------------------------------------- | ||
// TEST SETUP | ||
// ----------------------------------------------------------------------------- | ||
|
||
- (void)setUp { | ||
settings = [ConfigHelper valueForKey:@"valid_password_protected_server"]; | ||
|
||
session = [NMSSHSession connectToHost:[settings objectForKey:@"host"] | ||
withUsername:[settings objectForKey:@"user"]]; | ||
[session authenticateByPassword:[settings objectForKey:@"password"]]; | ||
assert([session isAuthorized]); | ||
} | ||
|
||
- (void)tearDown { | ||
if (channel) { | ||
[channel close]; | ||
channel = nil; | ||
} | ||
|
||
if (session) { | ||
[session disconnect]; | ||
session = nil; | ||
} | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
// SHELL EXECUTION TESTS | ||
// ----------------------------------------------------------------------------- | ||
|
||
- (void)testCreatingChannelWorks { | ||
STAssertNoThrow(channel = [[NMSSHChannel alloc] initWithSession:session], | ||
@"Setting up channel does not throw exception"); | ||
} | ||
|
||
- (void)testExecutingShellCommand { | ||
channel = [[NMSSHChannel alloc] initWithSession:session]; | ||
|
||
NSError *error = nil; | ||
STAssertNoThrow([channel execute:[settings objectForKey:@"execute_command"] | ||
error:&error], | ||
@"Execution should not throw an exception"); | ||
|
||
STAssertEqualObjects([channel lastResponse], | ||
[settings objectForKey:@"execute_expected_response"], | ||
@"Execution returns the expected response"); | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters