From d3b85d0226c7f6d3789d0637ffbaec8d481cb9ee Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 28 Aug 2006 11:13:56 +0000 Subject: [PATCH 1/1] Fix line endings (svn:eol-style properties and actual CRs). git-svn-id: svn://svn.tartarus.org/sgt/putty@6817 cda61777-01e9-0310-a592-d414129be87e --- sercfg.c | 334 +++++++++++----------- windows/winproxy.c | 434 ++++++++++++++--------------- windows/winser.c | 792 ++++++++++++++++++++++++++--------------------------- 3 files changed, 780 insertions(+), 780 deletions(-) diff --git a/sercfg.c b/sercfg.c index c75879c5..10b582f0 100644 --- a/sercfg.c +++ b/sercfg.c @@ -1,167 +1,167 @@ -/* - * sercfg.c - the serial-port specific parts of the PuTTY - * configuration box. Centralised as cross-platform code because - * more than one platform will want to use it, but not part of the - * main configuration. The expectation is that each platform's - * local config function will call out to ser_setup_config_box() if - * it needs to set up the standard serial stuff. (Of course, it can - * then apply local tweaks after ser_setup_config_box() returns, if - * it needs to.) - */ - -#include -#include - -#include "putty.h" -#include "dialog.h" -#include "storage.h" - -static void serial_parity_handler(union control *ctrl, void *dlg, - void *data, int event) -{ - static const struct { - const char *name; - int val; - } parities[] = { - {"None", SER_PAR_NONE}, - {"Odd", SER_PAR_ODD}, - {"Even", SER_PAR_EVEN}, - {"Mark", SER_PAR_MARK}, - {"Space", SER_PAR_SPACE}, - }; - int i; - Config *cfg = (Config *)data; - - if (event == EVENT_REFRESH) { - dlg_update_start(ctrl, dlg); - dlg_listbox_clear(ctrl, dlg); - for (i = 0; i < lenof(parities); i++) - dlg_listbox_addwithid(ctrl, dlg, parities[i].name, - parities[i].val); - for (i = 0; i < lenof(parities); i++) - if (cfg->serparity == parities[i].val) - dlg_listbox_select(ctrl, dlg, i); - dlg_update_done(ctrl, dlg); - } else if (event == EVENT_SELCHANGE) { - int i = dlg_listbox_index(ctrl, dlg); - if (i < 0) - i = SER_PAR_NONE; - else - i = dlg_listbox_getid(ctrl, dlg, i); - cfg->serparity = i; - } -} - -static void serial_flow_handler(union control *ctrl, void *dlg, - void *data, int event) -{ - static const struct { - const char *name; - int val; - } flows[] = { - {"None", SER_FLOW_NONE}, - {"XON/XOFF", SER_FLOW_XONXOFF}, - {"RTS/CTS", SER_FLOW_RTSCTS}, - {"DSR/DTR", SER_FLOW_DSRDTR}, - }; - int i; - Config *cfg = (Config *)data; - - if (event == EVENT_REFRESH) { - dlg_update_start(ctrl, dlg); - dlg_listbox_clear(ctrl, dlg); - for (i = 0; i < lenof(flows); i++) - dlg_listbox_addwithid(ctrl, dlg, flows[i].name, - flows[i].val); - for (i = 0; i < lenof(flows); i++) - if (cfg->serflow == flows[i].val) - dlg_listbox_select(ctrl, dlg, i); - dlg_update_done(ctrl, dlg); - } else if (event == EVENT_SELCHANGE) { - int i = dlg_listbox_index(ctrl, dlg); - if (i < 0) - i = SER_PAR_NONE; - else - i = dlg_listbox_getid(ctrl, dlg, i); - cfg->serflow = i; - } -} - -void ser_setup_config_box(struct controlbox *b, int midsession) -{ - struct controlset *s; - union control *c; - - /* - * Add the serial back end to the protocols list at the top of - * the config box. - */ - s = ctrl_getset(b, "Session", "hostport", - "Specify your connection by host name or IP address"); - { - int i; - extern void config_protocolbuttons_handler(union control *, void *, - void *, int); - for (i = 0; i < s->ncontrols; i++) { - c = s->ctrls[i]; - if (c->generic.type == CTRL_RADIO && - c->generic.handler == config_protocolbuttons_handler) { - c->radio.nbuttons++; - c->radio.ncolumns++; - c->radio.buttons = - sresize(c->radio.buttons, c->radio.nbuttons, char *); - c->radio.buttons[c->radio.nbuttons-1] = - dupstr("Serial"); - c->radio.buttondata = - sresize(c->radio.buttondata, c->radio.nbuttons, intorptr); - c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL); - if (c->radio.shortcuts) { - c->radio.shortcuts = - sresize(c->radio.shortcuts, c->radio.nbuttons, char); - c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT; - } - } - } - } - - /* - * Entirely new Connection/Serial panel for serial port - * configuration. - */ - ctrl_settitle(b, "Connection/Serial", - "Options controlling local serial lines"); - - if (!midsession) { - /* - * We don't permit switching to a different serial port in - * midflight, although we do allow all other - * reconfiguration. - */ - s = ctrl_getset(b, "Connection/Serial", "serline", - "Select a serial line"); - ctrl_editbox(s, "Serial line to connect to", 'l', 40, - HELPCTX(serial_line), - dlg_stdeditbox_handler, I(offsetof(Config,serline)), - I(sizeof(((Config *)0)->serline))); - } - - s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line"); - ctrl_editbox(s, "Speed (baud)", 's', 40, - HELPCTX(serial_speed), - dlg_stdeditbox_handler, I(offsetof(Config,serspeed)), I(-1)); - ctrl_editbox(s, "Data bits", 'b', 40, - HELPCTX(serial_databits), - dlg_stdeditbox_handler,I(offsetof(Config,serdatabits)),I(-1)); - /* - * Stop bits come in units of one half. - */ - ctrl_editbox(s, "Stop bits", 't', 40, - HELPCTX(serial_stopbits), - dlg_stdeditbox_handler,I(offsetof(Config,serstopbits)),I(-2)); - ctrl_droplist(s, "Parity", 'p', 40, - HELPCTX(serial_parity), - serial_parity_handler, I(0)); - ctrl_droplist(s, "Flow control", 'f', 40, - HELPCTX(serial_flow), - serial_flow_handler, I(0)); -} +/* + * sercfg.c - the serial-port specific parts of the PuTTY + * configuration box. Centralised as cross-platform code because + * more than one platform will want to use it, but not part of the + * main configuration. The expectation is that each platform's + * local config function will call out to ser_setup_config_box() if + * it needs to set up the standard serial stuff. (Of course, it can + * then apply local tweaks after ser_setup_config_box() returns, if + * it needs to.) + */ + +#include +#include + +#include "putty.h" +#include "dialog.h" +#include "storage.h" + +static void serial_parity_handler(union control *ctrl, void *dlg, + void *data, int event) +{ + static const struct { + const char *name; + int val; + } parities[] = { + {"None", SER_PAR_NONE}, + {"Odd", SER_PAR_ODD}, + {"Even", SER_PAR_EVEN}, + {"Mark", SER_PAR_MARK}, + {"Space", SER_PAR_SPACE}, + }; + int i; + Config *cfg = (Config *)data; + + if (event == EVENT_REFRESH) { + dlg_update_start(ctrl, dlg); + dlg_listbox_clear(ctrl, dlg); + for (i = 0; i < lenof(parities); i++) + dlg_listbox_addwithid(ctrl, dlg, parities[i].name, + parities[i].val); + for (i = 0; i < lenof(parities); i++) + if (cfg->serparity == parities[i].val) + dlg_listbox_select(ctrl, dlg, i); + dlg_update_done(ctrl, dlg); + } else if (event == EVENT_SELCHANGE) { + int i = dlg_listbox_index(ctrl, dlg); + if (i < 0) + i = SER_PAR_NONE; + else + i = dlg_listbox_getid(ctrl, dlg, i); + cfg->serparity = i; + } +} + +static void serial_flow_handler(union control *ctrl, void *dlg, + void *data, int event) +{ + static const struct { + const char *name; + int val; + } flows[] = { + {"None", SER_FLOW_NONE}, + {"XON/XOFF", SER_FLOW_XONXOFF}, + {"RTS/CTS", SER_FLOW_RTSCTS}, + {"DSR/DTR", SER_FLOW_DSRDTR}, + }; + int i; + Config *cfg = (Config *)data; + + if (event == EVENT_REFRESH) { + dlg_update_start(ctrl, dlg); + dlg_listbox_clear(ctrl, dlg); + for (i = 0; i < lenof(flows); i++) + dlg_listbox_addwithid(ctrl, dlg, flows[i].name, + flows[i].val); + for (i = 0; i < lenof(flows); i++) + if (cfg->serflow == flows[i].val) + dlg_listbox_select(ctrl, dlg, i); + dlg_update_done(ctrl, dlg); + } else if (event == EVENT_SELCHANGE) { + int i = dlg_listbox_index(ctrl, dlg); + if (i < 0) + i = SER_PAR_NONE; + else + i = dlg_listbox_getid(ctrl, dlg, i); + cfg->serflow = i; + } +} + +void ser_setup_config_box(struct controlbox *b, int midsession) +{ + struct controlset *s; + union control *c; + + /* + * Add the serial back end to the protocols list at the top of + * the config box. + */ + s = ctrl_getset(b, "Session", "hostport", + "Specify your connection by host name or IP address"); + { + int i; + extern void config_protocolbuttons_handler(union control *, void *, + void *, int); + for (i = 0; i < s->ncontrols; i++) { + c = s->ctrls[i]; + if (c->generic.type == CTRL_RADIO && + c->generic.handler == config_protocolbuttons_handler) { + c->radio.nbuttons++; + c->radio.ncolumns++; + c->radio.buttons = + sresize(c->radio.buttons, c->radio.nbuttons, char *); + c->radio.buttons[c->radio.nbuttons-1] = + dupstr("Serial"); + c->radio.buttondata = + sresize(c->radio.buttondata, c->radio.nbuttons, intorptr); + c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL); + if (c->radio.shortcuts) { + c->radio.shortcuts = + sresize(c->radio.shortcuts, c->radio.nbuttons, char); + c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT; + } + } + } + } + + /* + * Entirely new Connection/Serial panel for serial port + * configuration. + */ + ctrl_settitle(b, "Connection/Serial", + "Options controlling local serial lines"); + + if (!midsession) { + /* + * We don't permit switching to a different serial port in + * midflight, although we do allow all other + * reconfiguration. + */ + s = ctrl_getset(b, "Connection/Serial", "serline", + "Select a serial line"); + ctrl_editbox(s, "Serial line to connect to", 'l', 40, + HELPCTX(serial_line), + dlg_stdeditbox_handler, I(offsetof(Config,serline)), + I(sizeof(((Config *)0)->serline))); + } + + s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line"); + ctrl_editbox(s, "Speed (baud)", 's', 40, + HELPCTX(serial_speed), + dlg_stdeditbox_handler, I(offsetof(Config,serspeed)), I(-1)); + ctrl_editbox(s, "Data bits", 'b', 40, + HELPCTX(serial_databits), + dlg_stdeditbox_handler,I(offsetof(Config,serdatabits)),I(-1)); + /* + * Stop bits come in units of one half. + */ + ctrl_editbox(s, "Stop bits", 't', 40, + HELPCTX(serial_stopbits), + dlg_stdeditbox_handler,I(offsetof(Config,serstopbits)),I(-2)); + ctrl_droplist(s, "Parity", 'p', 40, + HELPCTX(serial_parity), + serial_parity_handler, I(0)); + ctrl_droplist(s, "Flow control", 'f', 40, + HELPCTX(serial_flow), + serial_flow_handler, I(0)); +} diff --git a/windows/winproxy.c b/windows/winproxy.c index 5fecfc25..c8221edf 100644 --- a/windows/winproxy.c +++ b/windows/winproxy.c @@ -1,217 +1,217 @@ -/* - * winproxy.c: Windows implementation of platform_new_connection(), - * supporting an OpenSSH-like proxy command via the winhandl.c - * mechanism. - */ - -#include -#include - -#define DEFINE_PLUG_METHOD_MACROS -#include "tree234.h" -#include "putty.h" -#include "network.h" -#include "proxy.h" - -typedef struct Socket_localproxy_tag *Local_Proxy_Socket; - -struct Socket_localproxy_tag { - const struct socket_function_table *fn; - /* the above variable absolutely *must* be the first in this structure */ - - HANDLE to_cmd_H, from_cmd_H; - struct handle *to_cmd_h, *from_cmd_h; - - char *error; - - Plug plug; - - void *privptr; -}; - -int localproxy_gotdata(struct handle *h, void *data, int len) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) handle_get_privdata(h); - - if (len < 0) { - return plug_closing(ps->plug, "Read error from local proxy command", - 0, 0); - } else if (len == 0) { - return plug_closing(ps->plug, NULL, 0, 0); - } else { - return plug_receive(ps->plug, 1, data, len); - } -} - -void localproxy_sentdata(struct handle *h, int new_backlog) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) handle_get_privdata(h); - - plug_sent(ps->plug, new_backlog); -} - -static Plug sk_localproxy_plug (Socket s, Plug p) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - Plug ret = ps->plug; - if (p) - ps->plug = p; - return ret; -} - -static void sk_localproxy_close (Socket s) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - - handle_free(ps->to_cmd_h); - handle_free(ps->from_cmd_h); - CloseHandle(ps->to_cmd_H); - CloseHandle(ps->from_cmd_H); - - sfree(ps); -} - -static int sk_localproxy_write (Socket s, const char *data, int len) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - - return handle_write(ps->to_cmd_h, data, len); -} - -static int sk_localproxy_write_oob(Socket s, const char *data, int len) -{ - /* - * oob data is treated as inband; nasty, but nothing really - * better we can do - */ - return sk_localproxy_write(s, data, len); -} - -static void sk_localproxy_flush(Socket s) -{ - /* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */ - /* do nothing */ -} - -static void sk_localproxy_set_private_ptr(Socket s, void *ptr) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - ps->privptr = ptr; -} - -static void *sk_localproxy_get_private_ptr(Socket s) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - return ps->privptr; -} - -static void sk_localproxy_set_frozen(Socket s, int is_frozen) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - - /* - * FIXME - */ -} - -static const char *sk_localproxy_socket_error(Socket s) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - return ps->error; -} - -Socket platform_new_connection(SockAddr addr, char *hostname, - int port, int privport, - int oobinline, int nodelay, int keepalive, - Plug plug, const Config *cfg) -{ - char *cmd; - - static const struct socket_function_table socket_fn_table = { - sk_localproxy_plug, - sk_localproxy_close, - sk_localproxy_write, - sk_localproxy_write_oob, - sk_localproxy_flush, - sk_localproxy_set_private_ptr, - sk_localproxy_get_private_ptr, - sk_localproxy_set_frozen, - sk_localproxy_socket_error - }; - - Local_Proxy_Socket ret; - HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us; - SECURITY_ATTRIBUTES sa; - STARTUPINFO si; - PROCESS_INFORMATION pi; - - if (cfg->proxy_type != PROXY_CMD) - return NULL; - - cmd = format_telnet_command(addr, port, cfg); - - { - char *msg = dupprintf("Starting local proxy command: %s", cmd); - /* We're allowed to pass NULL here, because we're part of the Windows - * front end so we know logevent doesn't expect any data. */ - logevent(NULL, msg); - sfree(msg); - } - - ret = snew(struct Socket_localproxy_tag); - ret->fn = &socket_fn_table; - ret->plug = plug; - ret->error = NULL; - - /* - * Create the pipes to the proxy command, and spawn the proxy - * command process. - */ - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; /* default */ - sa.bInheritHandle = TRUE; - if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { - ret->error = dupprintf("Unable to create pipes for proxy command"); - return (Socket)ret; - } - - if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { - CloseHandle(us_from_cmd); - CloseHandle(cmd_to_us); - ret->error = dupprintf("Unable to create pipes for proxy command"); - return (Socket)ret; - } - - SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); - SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); - - si.cb = sizeof(si); - si.lpReserved = NULL; - si.lpDesktop = NULL; - si.lpTitle = NULL; - si.dwFlags = STARTF_USESTDHANDLES; - si.cbReserved2 = 0; - si.lpReserved2 = NULL; - si.hStdInput = cmd_from_us; - si.hStdOutput = cmd_to_us; - si.hStdError = NULL; - CreateProcess(NULL, cmd, NULL, NULL, TRUE, - CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, - NULL, NULL, &si, &pi); - - CloseHandle(cmd_from_us); - CloseHandle(cmd_to_us); - - ret->to_cmd_H = us_to_cmd; - ret->from_cmd_H = us_from_cmd; - - ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata, - ret, 0); - ret->to_cmd_h = handle_output_new(ret->to_cmd_H, localproxy_sentdata, - ret, 0); - - /* We are responsible for this and don't need it any more */ - sk_addr_free(addr); - - return (Socket) ret; -} +/* + * winproxy.c: Windows implementation of platform_new_connection(), + * supporting an OpenSSH-like proxy command via the winhandl.c + * mechanism. + */ + +#include +#include + +#define DEFINE_PLUG_METHOD_MACROS +#include "tree234.h" +#include "putty.h" +#include "network.h" +#include "proxy.h" + +typedef struct Socket_localproxy_tag *Local_Proxy_Socket; + +struct Socket_localproxy_tag { + const struct socket_function_table *fn; + /* the above variable absolutely *must* be the first in this structure */ + + HANDLE to_cmd_H, from_cmd_H; + struct handle *to_cmd_h, *from_cmd_h; + + char *error; + + Plug plug; + + void *privptr; +}; + +int localproxy_gotdata(struct handle *h, void *data, int len) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) handle_get_privdata(h); + + if (len < 0) { + return plug_closing(ps->plug, "Read error from local proxy command", + 0, 0); + } else if (len == 0) { + return plug_closing(ps->plug, NULL, 0, 0); + } else { + return plug_receive(ps->plug, 1, data, len); + } +} + +void localproxy_sentdata(struct handle *h, int new_backlog) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) handle_get_privdata(h); + + plug_sent(ps->plug, new_backlog); +} + +static Plug sk_localproxy_plug (Socket s, Plug p) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + Plug ret = ps->plug; + if (p) + ps->plug = p; + return ret; +} + +static void sk_localproxy_close (Socket s) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + + handle_free(ps->to_cmd_h); + handle_free(ps->from_cmd_h); + CloseHandle(ps->to_cmd_H); + CloseHandle(ps->from_cmd_H); + + sfree(ps); +} + +static int sk_localproxy_write (Socket s, const char *data, int len) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + + return handle_write(ps->to_cmd_h, data, len); +} + +static int sk_localproxy_write_oob(Socket s, const char *data, int len) +{ + /* + * oob data is treated as inband; nasty, but nothing really + * better we can do + */ + return sk_localproxy_write(s, data, len); +} + +static void sk_localproxy_flush(Socket s) +{ + /* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */ + /* do nothing */ +} + +static void sk_localproxy_set_private_ptr(Socket s, void *ptr) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + ps->privptr = ptr; +} + +static void *sk_localproxy_get_private_ptr(Socket s) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + return ps->privptr; +} + +static void sk_localproxy_set_frozen(Socket s, int is_frozen) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + + /* + * FIXME + */ +} + +static const char *sk_localproxy_socket_error(Socket s) +{ + Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + return ps->error; +} + +Socket platform_new_connection(SockAddr addr, char *hostname, + int port, int privport, + int oobinline, int nodelay, int keepalive, + Plug plug, const Config *cfg) +{ + char *cmd; + + static const struct socket_function_table socket_fn_table = { + sk_localproxy_plug, + sk_localproxy_close, + sk_localproxy_write, + sk_localproxy_write_oob, + sk_localproxy_flush, + sk_localproxy_set_private_ptr, + sk_localproxy_get_private_ptr, + sk_localproxy_set_frozen, + sk_localproxy_socket_error + }; + + Local_Proxy_Socket ret; + HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us; + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + PROCESS_INFORMATION pi; + + if (cfg->proxy_type != PROXY_CMD) + return NULL; + + cmd = format_telnet_command(addr, port, cfg); + + { + char *msg = dupprintf("Starting local proxy command: %s", cmd); + /* We're allowed to pass NULL here, because we're part of the Windows + * front end so we know logevent doesn't expect any data. */ + logevent(NULL, msg); + sfree(msg); + } + + ret = snew(struct Socket_localproxy_tag); + ret->fn = &socket_fn_table; + ret->plug = plug; + ret->error = NULL; + + /* + * Create the pipes to the proxy command, and spawn the proxy + * command process. + */ + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = NULL; /* default */ + sa.bInheritHandle = TRUE; + if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { + ret->error = dupprintf("Unable to create pipes for proxy command"); + return (Socket)ret; + } + + if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { + CloseHandle(us_from_cmd); + CloseHandle(cmd_to_us); + ret->error = dupprintf("Unable to create pipes for proxy command"); + return (Socket)ret; + } + + SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); + + si.cb = sizeof(si); + si.lpReserved = NULL; + si.lpDesktop = NULL; + si.lpTitle = NULL; + si.dwFlags = STARTF_USESTDHANDLES; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + si.hStdInput = cmd_from_us; + si.hStdOutput = cmd_to_us; + si.hStdError = NULL; + CreateProcess(NULL, cmd, NULL, NULL, TRUE, + CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, + NULL, NULL, &si, &pi); + + CloseHandle(cmd_from_us); + CloseHandle(cmd_to_us); + + ret->to_cmd_H = us_to_cmd; + ret->from_cmd_H = us_from_cmd; + + ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata, + ret, 0); + ret->to_cmd_h = handle_output_new(ret->to_cmd_H, localproxy_sentdata, + ret, 0); + + /* We are responsible for this and don't need it any more */ + sk_addr_free(addr); + + return (Socket) ret; +} diff --git a/windows/winser.c b/windows/winser.c index f6def7aa..35a4ed4a 100644 --- a/windows/winser.c +++ b/windows/winser.c @@ -1,396 +1,396 @@ -/* - * Serial back end (Windows-specific). - */ - -/* - * TODO: - * - * - sending breaks? - * + looks as if you do this by calling SetCommBreak(handle), - * then waiting a bit, then doing ClearCommBreak(handle). A - * small job for timing.c, methinks. - * - * - why are we dropping data when talking to judicator? - */ - -#include -#include -#include - -#include "putty.h" - -#define SERIAL_MAX_BACKLOG 4096 - -typedef struct serial_backend_data { - HANDLE port; - struct handle *out, *in; - void *frontend; - int bufsize; -} *Serial; - -static void serial_terminate(Serial serial) -{ - if (serial->out) { - handle_free(serial->out); - serial->out = NULL; - } - if (serial->in) { - handle_free(serial->in); - serial->in = NULL; - } - if (serial->port) { - CloseHandle(serial->port); - serial->port = NULL; - } -} - -static int serial_gotdata(struct handle *h, void *data, int len) -{ - Serial serial = (Serial)handle_get_privdata(h); - if (len <= 0) { - const char *error_msg; - - /* - * Currently, len==0 should never happen because we're - * ignoring EOFs. However, it seems not totally impossible - * that this same back end might be usable to talk to named - * pipes or some other non-serial device, in which case EOF - * may become meaningful here. - */ - if (len == 0) - error_msg = "End of file reading from serial device"; - else - error_msg = "Error reading from serial device"; - - serial_terminate(serial); - - notify_remote_exit(serial->frontend); - - logevent(serial->frontend, error_msg); - - connection_fatal(serial->frontend, "%s", error_msg); - - return 0; /* placate optimiser */ - } else { - return from_backend(serial->frontend, 0, data, len); - } -} - -static void serial_sentdata(struct handle *h, int new_backlog) -{ - Serial serial = (Serial)handle_get_privdata(h); - if (new_backlog < 0) { - const char *error_msg = "Error writing to serial device"; - - serial_terminate(serial); - - notify_remote_exit(serial->frontend); - - logevent(serial->frontend, error_msg); - - connection_fatal(serial->frontend, "%s", error_msg); - } else { - serial->bufsize = new_backlog; - } -} - -static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg) -{ - DCB dcb; - COMMTIMEOUTS timeouts; - - /* - * Set up the serial port parameters. If we can't even - * GetCommState, we ignore the problem on the grounds that the - * user might have pointed us at some other type of two-way - * device instead of a serial port. - */ - if (GetCommState(serport, &dcb)) { - char *msg; - const char *str; - - /* - * Boilerplate. - */ - dcb.fBinary = TRUE; - dcb.fDtrControl = DTR_CONTROL_ENABLE; - dcb.fDsrSensitivity = FALSE; - dcb.fTXContinueOnXoff = FALSE; - dcb.fOutX = FALSE; - dcb.fInX = FALSE; - dcb.fErrorChar = FALSE; - dcb.fNull = FALSE; - dcb.fRtsControl = RTS_CONTROL_ENABLE; - dcb.fAbortOnError = FALSE; - dcb.fOutxCtsFlow = FALSE; - dcb.fOutxDsrFlow = FALSE; - - /* - * Configurable parameters. - */ - dcb.BaudRate = cfg->serspeed; - msg = dupprintf("Configuring baud rate %d", cfg->serspeed); - logevent(serial->frontend, msg); - sfree(msg); - - dcb.ByteSize = cfg->serdatabits; - msg = dupprintf("Configuring %d data bits", cfg->serdatabits); - logevent(serial->frontend, msg); - sfree(msg); - - switch (cfg->serstopbits) { - case 2: dcb.StopBits = ONESTOPBIT; str = "1"; break; - case 3: dcb.StopBits = ONE5STOPBITS; str = "1.5"; break; - case 4: dcb.StopBits = TWOSTOPBITS; str = "2"; break; - default: return "Invalid number of stop bits (need 1, 1.5 or 2)"; - } - msg = dupprintf("Configuring %s data bits", str); - logevent(serial->frontend, msg); - sfree(msg); - - switch (cfg->serparity) { - case SER_PAR_NONE: dcb.Parity = NOPARITY; str = "no"; break; - case SER_PAR_ODD: dcb.Parity = ODDPARITY; str = "odd"; break; - case SER_PAR_EVEN: dcb.Parity = EVENPARITY; str = "even"; break; - case SER_PAR_MARK: dcb.Parity = MARKPARITY; str = "mark"; break; - case SER_PAR_SPACE: dcb.Parity = SPACEPARITY; str = "space"; break; - } - msg = dupprintf("Configuring %s parity", str); - logevent(serial->frontend, msg); - sfree(msg); - - switch (cfg->serflow) { - case SER_FLOW_NONE: - str = "no"; - break; - case SER_FLOW_XONXOFF: - dcb.fOutX = dcb.fInX = TRUE; - str = "XON/XOFF"; - break; - case SER_FLOW_RTSCTS: - dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; - dcb.fOutxCtsFlow = TRUE; - str = "RTS/CTS"; - break; - case SER_FLOW_DSRDTR: - dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; - dcb.fOutxDsrFlow = TRUE; - str = "DSR/DTR"; - break; - } - msg = dupprintf("Configuring %s flow control", str); - logevent(serial->frontend, msg); - sfree(msg); - - if (!SetCommState(serport, &dcb)) - return "Unable to configure serial port"; - - timeouts.ReadIntervalTimeout = 1; - timeouts.ReadTotalTimeoutMultiplier = 0; - timeouts.ReadTotalTimeoutConstant = 0; - timeouts.WriteTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutConstant = 0; - if (!SetCommTimeouts(serport, &timeouts)) - return "Unable to configure serial timeouts"; - } - - return NULL; -} - -/* - * Called to set up the serial connection. - * - * Returns an error message, or NULL on success. - * - * Also places the canonical host name into `realhost'. It must be - * freed by the caller. - */ -static const char *serial_init(void *frontend_handle, void **backend_handle, - Config *cfg, - char *host, int port, char **realhost, int nodelay, - int keepalive) -{ - Serial serial; - HANDLE serport; - const char *err; - - serial = snew(struct serial_backend_data); - serial->port = NULL; - serial->out = serial->in = NULL; - *backend_handle = serial; - - serial->frontend = frontend_handle; - - { - char *msg = dupprintf("Opening serial device %s", host); - logevent(serial->frontend, msg); - } - - serport = CreateFile(cfg->serline, GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (serport == INVALID_HANDLE_VALUE) - return "Unable to open serial port"; - - err = serial_configure(serial, serport, cfg); - if (err) - return err; - - serial->port = serport; - serial->out = handle_output_new(serport, serial_sentdata, serial, - HANDLE_FLAG_OVERLAPPED); - serial->in = handle_input_new(serport, serial_gotdata, serial, - HANDLE_FLAG_OVERLAPPED | - HANDLE_FLAG_IGNOREEOF); - - *realhost = dupstr(cfg->serline); - - return NULL; -} - -static void serial_free(void *handle) -{ - Serial serial = (Serial) handle; - - serial_terminate(serial); - sfree(serial); -} - -static void serial_reconfig(void *handle, Config *cfg) -{ - Serial serial = (Serial) handle; - const char *err; - - err = serial_configure(serial, serial->port, cfg); - - /* - * FIXME: what should we do if err returns something? - */ -} - -/* - * Called to send data down the serial connection. - */ -static int serial_send(void *handle, char *buf, int len) -{ - Serial serial = (Serial) handle; - - if (serial->out == NULL) - return 0; - - serial->bufsize = handle_write(serial->out, buf, len); - return serial->bufsize; -} - -/* - * Called to query the current sendability status. - */ -static int serial_sendbuffer(void *handle) -{ - Serial serial = (Serial) handle; - return serial->bufsize; -} - -/* - * Called to set the size of the window - */ -static void serial_size(void *handle, int width, int height) -{ - /* Do nothing! */ - return; -} - -/* - * Send serial special codes. - */ -static void serial_special(void *handle, Telnet_Special code) -{ - /* - * FIXME: serial break? XON? XOFF? - */ - return; -} - -/* - * Return a list of the special codes that make sense in this - * protocol. - */ -static const struct telnet_special *serial_get_specials(void *handle) -{ - /* - * FIXME: serial break? XON? XOFF? - */ - return NULL; -} - -static int serial_connected(void *handle) -{ - return 1; /* always connected */ -} - -static int serial_sendok(void *handle) -{ - return 1; -} - -static void serial_unthrottle(void *handle, int backlog) -{ - Serial serial = (Serial) handle; - if (serial->in) - handle_unthrottle(serial->in, backlog); -} - -static int serial_ldisc(void *handle, int option) -{ - /* - * Local editing and local echo are off by default. - */ - return 0; -} - -static void serial_provide_ldisc(void *handle, void *ldisc) -{ - /* This is a stub. */ -} - -static void serial_provide_logctx(void *handle, void *logctx) -{ - /* This is a stub. */ -} - -static int serial_exitcode(void *handle) -{ - Serial serial = (Serial) handle; - if (serial->port != NULL) - return -1; /* still connected */ - else - /* Exit codes are a meaningless concept with serial ports */ - return INT_MAX; -} - -/* - * cfg_info for Serial does nothing at all. - */ -static int serial_cfg_info(void *handle) -{ - return 0; -} - -Backend serial_backend = { - serial_init, - serial_free, - serial_reconfig, - serial_send, - serial_sendbuffer, - serial_size, - serial_special, - serial_get_specials, - serial_connected, - serial_exitcode, - serial_sendok, - serial_ldisc, - serial_provide_ldisc, - serial_provide_logctx, - serial_unthrottle, - serial_cfg_info, - 1 -}; +/* + * Serial back end (Windows-specific). + */ + +/* + * TODO: + * + * - sending breaks? + * + looks as if you do this by calling SetCommBreak(handle), + * then waiting a bit, then doing ClearCommBreak(handle). A + * small job for timing.c, methinks. + * + * - why are we dropping data when talking to judicator? + */ + +#include +#include +#include + +#include "putty.h" + +#define SERIAL_MAX_BACKLOG 4096 + +typedef struct serial_backend_data { + HANDLE port; + struct handle *out, *in; + void *frontend; + int bufsize; +} *Serial; + +static void serial_terminate(Serial serial) +{ + if (serial->out) { + handle_free(serial->out); + serial->out = NULL; + } + if (serial->in) { + handle_free(serial->in); + serial->in = NULL; + } + if (serial->port) { + CloseHandle(serial->port); + serial->port = NULL; + } +} + +static int serial_gotdata(struct handle *h, void *data, int len) +{ + Serial serial = (Serial)handle_get_privdata(h); + if (len <= 0) { + const char *error_msg; + + /* + * Currently, len==0 should never happen because we're + * ignoring EOFs. However, it seems not totally impossible + * that this same back end might be usable to talk to named + * pipes or some other non-serial device, in which case EOF + * may become meaningful here. + */ + if (len == 0) + error_msg = "End of file reading from serial device"; + else + error_msg = "Error reading from serial device"; + + serial_terminate(serial); + + notify_remote_exit(serial->frontend); + + logevent(serial->frontend, error_msg); + + connection_fatal(serial->frontend, "%s", error_msg); + + return 0; /* placate optimiser */ + } else { + return from_backend(serial->frontend, 0, data, len); + } +} + +static void serial_sentdata(struct handle *h, int new_backlog) +{ + Serial serial = (Serial)handle_get_privdata(h); + if (new_backlog < 0) { + const char *error_msg = "Error writing to serial device"; + + serial_terminate(serial); + + notify_remote_exit(serial->frontend); + + logevent(serial->frontend, error_msg); + + connection_fatal(serial->frontend, "%s", error_msg); + } else { + serial->bufsize = new_backlog; + } +} + +static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg) +{ + DCB dcb; + COMMTIMEOUTS timeouts; + + /* + * Set up the serial port parameters. If we can't even + * GetCommState, we ignore the problem on the grounds that the + * user might have pointed us at some other type of two-way + * device instead of a serial port. + */ + if (GetCommState(serport, &dcb)) { + char *msg; + const char *str; + + /* + * Boilerplate. + */ + dcb.fBinary = TRUE; + dcb.fDtrControl = DTR_CONTROL_ENABLE; + dcb.fDsrSensitivity = FALSE; + dcb.fTXContinueOnXoff = FALSE; + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + dcb.fErrorChar = FALSE; + dcb.fNull = FALSE; + dcb.fRtsControl = RTS_CONTROL_ENABLE; + dcb.fAbortOnError = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + + /* + * Configurable parameters. + */ + dcb.BaudRate = cfg->serspeed; + msg = dupprintf("Configuring baud rate %d", cfg->serspeed); + logevent(serial->frontend, msg); + sfree(msg); + + dcb.ByteSize = cfg->serdatabits; + msg = dupprintf("Configuring %d data bits", cfg->serdatabits); + logevent(serial->frontend, msg); + sfree(msg); + + switch (cfg->serstopbits) { + case 2: dcb.StopBits = ONESTOPBIT; str = "1"; break; + case 3: dcb.StopBits = ONE5STOPBITS; str = "1.5"; break; + case 4: dcb.StopBits = TWOSTOPBITS; str = "2"; break; + default: return "Invalid number of stop bits (need 1, 1.5 or 2)"; + } + msg = dupprintf("Configuring %s data bits", str); + logevent(serial->frontend, msg); + sfree(msg); + + switch (cfg->serparity) { + case SER_PAR_NONE: dcb.Parity = NOPARITY; str = "no"; break; + case SER_PAR_ODD: dcb.Parity = ODDPARITY; str = "odd"; break; + case SER_PAR_EVEN: dcb.Parity = EVENPARITY; str = "even"; break; + case SER_PAR_MARK: dcb.Parity = MARKPARITY; str = "mark"; break; + case SER_PAR_SPACE: dcb.Parity = SPACEPARITY; str = "space"; break; + } + msg = dupprintf("Configuring %s parity", str); + logevent(serial->frontend, msg); + sfree(msg); + + switch (cfg->serflow) { + case SER_FLOW_NONE: + str = "no"; + break; + case SER_FLOW_XONXOFF: + dcb.fOutX = dcb.fInX = TRUE; + str = "XON/XOFF"; + break; + case SER_FLOW_RTSCTS: + dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; + dcb.fOutxCtsFlow = TRUE; + str = "RTS/CTS"; + break; + case SER_FLOW_DSRDTR: + dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; + dcb.fOutxDsrFlow = TRUE; + str = "DSR/DTR"; + break; + } + msg = dupprintf("Configuring %s flow control", str); + logevent(serial->frontend, msg); + sfree(msg); + + if (!SetCommState(serport, &dcb)) + return "Unable to configure serial port"; + + timeouts.ReadIntervalTimeout = 1; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + if (!SetCommTimeouts(serport, &timeouts)) + return "Unable to configure serial timeouts"; + } + + return NULL; +} + +/* + * Called to set up the serial connection. + * + * Returns an error message, or NULL on success. + * + * Also places the canonical host name into `realhost'. It must be + * freed by the caller. + */ +static const char *serial_init(void *frontend_handle, void **backend_handle, + Config *cfg, + char *host, int port, char **realhost, int nodelay, + int keepalive) +{ + Serial serial; + HANDLE serport; + const char *err; + + serial = snew(struct serial_backend_data); + serial->port = NULL; + serial->out = serial->in = NULL; + *backend_handle = serial; + + serial->frontend = frontend_handle; + + { + char *msg = dupprintf("Opening serial device %s", host); + logevent(serial->frontend, msg); + } + + serport = CreateFile(cfg->serline, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (serport == INVALID_HANDLE_VALUE) + return "Unable to open serial port"; + + err = serial_configure(serial, serport, cfg); + if (err) + return err; + + serial->port = serport; + serial->out = handle_output_new(serport, serial_sentdata, serial, + HANDLE_FLAG_OVERLAPPED); + serial->in = handle_input_new(serport, serial_gotdata, serial, + HANDLE_FLAG_OVERLAPPED | + HANDLE_FLAG_IGNOREEOF); + + *realhost = dupstr(cfg->serline); + + return NULL; +} + +static void serial_free(void *handle) +{ + Serial serial = (Serial) handle; + + serial_terminate(serial); + sfree(serial); +} + +static void serial_reconfig(void *handle, Config *cfg) +{ + Serial serial = (Serial) handle; + const char *err; + + err = serial_configure(serial, serial->port, cfg); + + /* + * FIXME: what should we do if err returns something? + */ +} + +/* + * Called to send data down the serial connection. + */ +static int serial_send(void *handle, char *buf, int len) +{ + Serial serial = (Serial) handle; + + if (serial->out == NULL) + return 0; + + serial->bufsize = handle_write(serial->out, buf, len); + return serial->bufsize; +} + +/* + * Called to query the current sendability status. + */ +static int serial_sendbuffer(void *handle) +{ + Serial serial = (Serial) handle; + return serial->bufsize; +} + +/* + * Called to set the size of the window + */ +static void serial_size(void *handle, int width, int height) +{ + /* Do nothing! */ + return; +} + +/* + * Send serial special codes. + */ +static void serial_special(void *handle, Telnet_Special code) +{ + /* + * FIXME: serial break? XON? XOFF? + */ + return; +} + +/* + * Return a list of the special codes that make sense in this + * protocol. + */ +static const struct telnet_special *serial_get_specials(void *handle) +{ + /* + * FIXME: serial break? XON? XOFF? + */ + return NULL; +} + +static int serial_connected(void *handle) +{ + return 1; /* always connected */ +} + +static int serial_sendok(void *handle) +{ + return 1; +} + +static void serial_unthrottle(void *handle, int backlog) +{ + Serial serial = (Serial) handle; + if (serial->in) + handle_unthrottle(serial->in, backlog); +} + +static int serial_ldisc(void *handle, int option) +{ + /* + * Local editing and local echo are off by default. + */ + return 0; +} + +static void serial_provide_ldisc(void *handle, void *ldisc) +{ + /* This is a stub. */ +} + +static void serial_provide_logctx(void *handle, void *logctx) +{ + /* This is a stub. */ +} + +static int serial_exitcode(void *handle) +{ + Serial serial = (Serial) handle; + if (serial->port != NULL) + return -1; /* still connected */ + else + /* Exit codes are a meaningless concept with serial ports */ + return INT_MAX; +} + +/* + * cfg_info for Serial does nothing at all. + */ +static int serial_cfg_info(void *handle) +{ + return 0; +} + +Backend serial_backend = { + serial_init, + serial_free, + serial_reconfig, + serial_send, + serial_sendbuffer, + serial_size, + serial_special, + serial_get_specials, + serial_connected, + serial_exitcode, + serial_sendok, + serial_ldisc, + serial_provide_ldisc, + serial_provide_logctx, + serial_unthrottle, + serial_cfg_info, + 1 +}; -- 2.11.0