objective c - NSTask for SSH using PTY -
i'm trying write app programmatically log in remote device using ssh expect script (i know can use expect in obj-c).
i have researched lot on , know need use pty. code have works fine telnet can't seem ssh work. seems though ssh not using pty ask password. when execute following code see device asking password, don't see nslog output.
i'm new , on head, i'd appreciate can me working.
#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 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: not set pty 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 match!!"); [buff setstring:@""]; [masterhandle writedata:[@"bhughes\n" datausingencoding:nsutf8stringencoding]]; } nslog(@"exiting function.\n"); [masterhandle waitfordatainbackgroundandnotify]; }]; [task waituntilexit]; nslog(@"program complete.\n"); } return 0; }
as far know, nstask not support pty ability. working ssh requires interactive pty device context.
the simplest way forkpty, forks process itself, cannot used nstask.
finally wrote wrapper class manages forkpty. forks child process , calls forkpty , execve.
here's implementation: https://github.com/eonil/pseudoteletypewriter.swift
you can read/write using single master device file handle. confirmed sudo working, , believe ssh should work fine.
Comments
Post a Comment