X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/9fab77dc00ff2183dd642f4f088d2d54ed3d5887..8f1612752a89ea821dbd63491aef858f7f7e5bef:/plink.c diff --git a/plink.c b/plink.c index b1bebf98..41a5001e 100644 --- a/plink.c +++ b/plink.c @@ -16,8 +16,17 @@ #include "storage.h" #include "tree234.h" +#define WM_AGENT_CALLBACK (WM_XUSER + 4) + #define MAX_STDIN_BACKLOG 4096 +struct agent_callback { + void (*callback)(void *, void *, int); + void *callback_ctx; + void *data; + int len; +}; + void fatalbox(char *p, ...) { va_list ap; @@ -187,6 +196,19 @@ int from_backend(void *frontend_handle, int is_stderr, return osize + esize; } +static DWORD main_thread_id; + +void agent_schedule_callback(void (*callback)(void *, void *, int), + void *callback_ctx, void *data, int len) +{ + struct agent_callback *c = snew(struct agent_callback); + c->callback = callback; + c->callback_ctx = callback_ctx; + c->data = data; + c->len = len; + PostThreadMessage(main_thread_id, WM_AGENT_CALLBACK, 0, (LPARAM)c); +} + /* * Short description of parameters. */ @@ -207,6 +229,7 @@ static void usage(void) printf(" -batch disable all interactive prompts\n"); printf("The following options only apply to SSH connections:\n"); printf(" -pw passw login with specified password\n"); + printf(" -D listen-port Dynamic SOCKS-based port forwarding\n"); printf(" -L listen-port:host:port Forward local port to " "remote address\n"); printf(" -R listen-port:host:port Forward remote port to" @@ -217,6 +240,7 @@ static void usage(void) printf(" -1 -2 force use of particular protocol version\n"); printf(" -C enable compression\n"); printf(" -i key private key file for authentication\n"); + printf(" -s remote command is an SSH subsystem (SSH-2 only)\n"); exit(1); } @@ -256,6 +280,7 @@ int main(int argc, char **argv) int connopen; int exitcode; int errors; + int use_subsystem = 0; ssh_get_line = console_get_line; @@ -308,6 +333,9 @@ int main(int argc, char **argv) continue; } else if (!strcmp(p, "-batch")) { console_batch_mode = 1; + } else if (!strcmp(p, "-s")) { + /* Save status to write to cfg later. */ + use_subsystem = 1; } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = 1; @@ -410,13 +438,13 @@ int main(int argc, char **argv) while (*p) { if (cmdlen >= cmdsize) { cmdsize = cmdlen + 512; - command = srealloc(command, cmdsize); + command = sresize(command, cmdsize, char); } command[cmdlen++]=*p++; } if (cmdlen >= cmdsize) { cmdsize = cmdlen + 512; - command = srealloc(command, cmdsize); + command = sresize(command, cmdsize, char); } command[cmdlen++]=' '; /* always add trailing space */ if (--argc) p = *++argv; @@ -466,6 +494,12 @@ int main(int argc, char **argv) cmdline_run_saved(&cfg); /* + * Apply subsystem status. + */ + if (use_subsystem) + cfg.ssh_subsys = TRUE; + + /* * Trim a colon suffix off the hostname if it's there. */ cfg.host[strcspn(cfg.host, ":")] = '\0'; @@ -535,7 +569,7 @@ int main(int argc, char **argv) */ netevent = CreateEvent(NULL, FALSE, FALSE, NULL); { - char *error; + const char *error; char *realhost; /* nodelay is only useful if stdin is a character device (console) */ int nodelay = cfg.tcp_nodelay && @@ -564,6 +598,8 @@ int main(int argc, char **argv) GetConsoleMode(inhandle, &orig_console_mode); SetConsoleMode(inhandle, ENABLE_PROCESSED_INPUT); + main_thread_id = GetCurrentThreadId(); + /* * Turn off ECHO and LINE input modes. We don't care if this * call fails, because we know we aren't necessarily running in @@ -628,7 +664,8 @@ int main(int argc, char **argv) sending = TRUE; } - n = WaitForMultipleObjects(4, handles, FALSE, INFINITE); + n = MsgWaitForMultipleObjects(4, handles, FALSE, INFINITE, + QS_POSTMESSAGE); if (n == 0) { WSANETWORKEVENTS things; SOCKET socket; @@ -651,7 +688,7 @@ int main(int argc, char **argv) /* Expand the buffer if necessary. */ if (i > sksize) { sksize = i + 16; - sklist = srealloc(sklist, sksize * sizeof(*sklist)); + sklist = sresize(sklist, sksize, SOCKET); } /* Retrieve the sockets into sklist. */ @@ -726,6 +763,15 @@ int main(int argc, char **argv) back->unthrottle(backhandle, bufchain_size(&stdout_data) + bufchain_size(&stderr_data)); } + } else if (n == 4) { + MSG msg; + while (PeekMessage(&msg, INVALID_HANDLE_VALUE, + WM_AGENT_CALLBACK, WM_AGENT_CALLBACK, + PM_REMOVE)) { + struct agent_callback *c = (struct agent_callback *)msg.lParam; + c->callback(c->callback_ctx, c->data, c->len); + sfree(c); + } } if (!reading && back->sendbuffer(backhandle) < MAX_STDIN_BACKLOG) { SetEvent(idata.eventback);