Objective c 使用PTY请求SSH
我正在尝试编写一个应用程序,它将使用SSH以编程方式登录到远程设备,就像使用expect脚本一样(我知道我可以使用expect,但我希望在Obj-c中这样做) 我对此做了很多研究,知道我需要使用pty。我的代码在telnet上运行良好,但我似乎无法让ssh正常工作。SSH似乎没有使用pty请求密码。当我执行以下代码时,我看到设备询问密码,但我没有看到NSLog输出 我对这一点很陌生,可能有点不知所措,但我真的很感激任何能帮助我实现这一目标的人Objective c 使用PTY请求SSH,objective-c,ssh,nstask,pty,Objective C,Ssh,Nstask,Pty,我正在尝试编写一个应用程序,它将使用SSH以编程方式登录到远程设备,就像使用expect脚本一样(我知道我可以使用expect,但我希望在Obj-c中这样做) 我对此做了很多研究,知道我需要使用pty。我的代码在telnet上运行良好,但我似乎无法让ssh正常工作。SSH似乎没有使用pty请求密码。当我执行以下代码时,我看到设备询问密码,但我没有看到NSLog输出 我对这一点很陌生,可能有点不知所措,但我真的很感激任何能帮助我实现这一目标的人 #import <Foundation/Fou
#import <Foundation/Foundation.h>
#import <util.h>
@interface NSTask (PTY)
- (NSFileHandle *)masterSideOfPTYOrError:(NSError **)error;
@end
@implementation NSTask (PTY)
- (NSFileHandle *)masterSideOfPTYOrError:(NSError *__autoreleasing *)error {
int fdMaster, fdSlave;
int rc = openpty(&fdMaster, &fdSlave, NULL, NULL, NULL);
if (rc != 0) {
if (error) {
*error = [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil];
}
return NULL;
}
fcntl(fdMaster, F_SETFD, FD_CLOEXEC);
fcntl(fdSlave, F_SETFD, FD_CLOEXEC);
NSFileHandle *masterHandle = [[NSFileHandle alloc] initWithFileDescriptor:fdMaster closeOnDealloc:YES];
NSFileHandle *slaveHandle = [[NSFileHandle alloc] initWithFileDescriptor:fdSlave closeOnDealloc:YES];
self.standardInput = slaveHandle;
self.standardOutput = slaveHandle;
return masterHandle;
}
@end
据我所知,
NSTask
不支持pty
功能。使用类似于ssh的东西需要交互式pty设备上下文
最简单的方法是,但这会分叉进程本身,因此不能与NSTask
一起使用
最后,我编写了一个包装器类来管理forkpty
。分叉子进程并调用forkpty
和execve
以下是我的实现:
您可以使用单个主设备文件句柄进行读/写。
我确认了
sudo
正在工作,我相信ssh
也应该可以正常工作。您是否可以将其更新为Swift 3.0,因为它应该是稳定的,并且将来的版本将向后兼容?
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/ssh"];
[task setArguments:@[@"user@192.168.1.1"]];
NSError *error;
NSFileHandle *masterHandle = [task masterSideOfPTYOrError:&error];
if (!masterHandle) {
NSLog(@"error: could not set up PTY for task: %@", error);
exit(0);
}
[task launch];
[masterHandle waitForDataInBackgroundAndNotify];
NSMutableString *buff = [[NSMutableString alloc] init];
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
object:masterHandle queue:nil
usingBlock:^(NSNotification *note)
{
NSData *outData = [masterHandle availableData];
NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
[buff appendString:outStr];
NSLog(@"output: %@", outStr);
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"sername:"
options:NSRegularExpressionCaseInsensitive
error:nil];
NSTextCheckingResult *match = [regex firstMatchInString:buff
options:0
range:NSMakeRange(0, [buff length])];
if (match) {
NSLog(@"got a match!!");
[buff setString:@""];
[masterHandle writeData:[@"bhughes\n" dataUsingEncoding:NSUTF8StringEncoding]];
}
NSLog(@"Exiting function.\n");
[masterHandle waitForDataInBackgroundAndNotify];
}];
[task waitUntilExit];
NSLog(@"Program complete.\n");
}
return 0;
}