static int conf_set_console(const char *valstr) { conf_set_bool(&cmdline_config.console, valstr, 0); if (cmdline_config.console){ conf_set_bool(&cmdline_config.gui, NULL, 0); } return 0; }
static int conf_set_gui(const char *valstr) { conf_set_bool(&cmdline_config.gui, valstr, 0); if (cmdline_config.gui){ } return 0; }
static int conf_set_debug(const char *valstr) { conf_set_bool(&cmdline_config.debug, valstr, 0); if (cmdline_config.debug) eventlog_set_debugmode(1); #ifdef DO_DAEMONIZE cmdline_config.foreground = 1; #endif return 0; }
static int conf_set_version(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { std::printf(D2CS_VERSION"\n"); exitflag = 1; } return 0; }
static int conf_set_version(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { printf(PVPGN_SOFTWARE" version "PVPGN_VERSION"\n"); exitflag = 1; } return 0; }
static int conf_set_service(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { Win32_ServiceRun(); exitflag = 1; } return 0; }
static int conf_set_help(const char *valstr) { unsigned tmp = 0; conf_set_bool(&tmp, valstr, 0); if (tmp) { usage(); exitflag = 1; } return 0; }
static int conf_setdef_gamelist_showall(void) { return conf_set_bool(&prefs_conf.gamelist_showall,NULL,0); }
static int conf_set_gamelist_showall(const char* valstr) { return conf_set_bool(&prefs_conf.gamelist_showall,valstr,0); }
static int conf_setdef_allow_newchar(void) { return conf_set_bool(&prefs_conf.allow_newchar,NULL,1); }
static int conf_set_allow_newchar(const char* valstr) { return conf_set_bool(&prefs_conf.allow_newchar,valstr,0); }
static int conf_setdef_allow_convert(void) { return conf_set_bool(&prefs_conf.allow_convert,NULL,0); }
static int conf_set_allow_convert(const char* valstr) { return conf_set_bool(&prefs_conf.allow_convert,valstr,0); }
static int conf_set_foreground(const char *valstr) { return conf_set_bool(&cmdline_config.foreground, valstr, 0); }
int main(int argc, char **argv) { bool sending; SOCKET *sklist; size_t skcount, sksize; int exitcode; bool errors; bool use_subsystem = false; bool just_test_share_exists = false; enum TriState sanitise_stdout = AUTO, sanitise_stderr = AUTO; unsigned long now, next, then; const struct BackendVtable *vt; dll_hijacking_protection(); sklist = NULL; skcount = sksize = 0; /* * Initialise port and protocol to sensible defaults. (These * will be overridden by more or less anything.) */ default_protocol = PROT_SSH; default_port = 22; flags = 0; cmdline_tooltype |= (TOOLTYPE_HOST_ARG | TOOLTYPE_HOST_ARG_CAN_BE_SESSION | TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX | TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD); /* * Process the command line. */ conf = conf_new(); do_defaults(NULL, conf); loaded_session = false; default_protocol = conf_get_int(conf, CONF_protocol); default_port = conf_get_int(conf, CONF_port); errors = false; { /* * Override the default protocol if PLINK_PROTOCOL is set. */ char *p = getenv("PLINK_PROTOCOL"); if (p) { const struct BackendVtable *vt = backend_vt_from_name(p); if (vt) { default_protocol = vt->protocol; default_port = vt->default_port; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); } } } while (--argc) { char *p = *++argv; int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL), 1, conf); if (ret == -2) { fprintf(stderr, "plink: option \"%s\" requires an argument\n", p); errors = true; } else if (ret == 2) { --argc, ++argv; } else if (ret == 1) { continue; } else if (!strcmp(p, "-batch")) { console_batch_mode = true; } else if (!strcmp(p, "-s")) { /* Save status to write to conf later. */ use_subsystem = true; } else if (!strcmp(p, "-V") || !strcmp(p, "--version")) { version(); } else if (!strcmp(p, "--help")) { usage(); } else if (!strcmp(p, "-pgpfp")) { pgp_fingerprints(); exit(1); } else if (!strcmp(p, "-shareexists")) { just_test_share_exists = true; } else if (!strcmp(p, "-sanitise-stdout") || !strcmp(p, "-sanitize-stdout")) { sanitise_stdout = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stdout") || !strcmp(p, "-no-sanitize-stdout")) { sanitise_stdout = FORCE_OFF; } else if (!strcmp(p, "-sanitise-stderr") || !strcmp(p, "-sanitize-stderr")) { sanitise_stderr = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stderr") || !strcmp(p, "-no-sanitize-stderr")) { sanitise_stderr = FORCE_OFF; } else if (!strcmp(p, "-no-antispoof")) { console_antispoof_prompt = false; } else if (*p != '-') { strbuf *cmdbuf = strbuf_new(); while (argc > 0) { if (cmdbuf->len > 0) put_byte(cmdbuf, ' '); /* add space separator */ put_datapl(cmdbuf, ptrlen_from_asciz(p)); if (--argc > 0) p = *++argv; } conf_set_str(conf, CONF_remote_cmd, cmdbuf->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ strbuf_free(cmdbuf); break; /* done with cmdline */ } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = true; } } if (errors) return 1; if (!cmdline_host_ok(conf)) { usage(); } prepare_session(conf); /* * Perform command-line overrides on session configuration. */ cmdline_run_saved(conf); /* * Apply subsystem status. */ if (use_subsystem) conf_set_bool(conf, CONF_ssh_subsys, true); if (!*conf_get_str(conf, CONF_remote_cmd) && !*conf_get_str(conf, CONF_remote_cmd2) && !*conf_get_str(conf, CONF_ssh_nc_host)) flags |= FLAG_INTERACTIVE; /* * Select protocol. This is farmed out into a table in a * separate file to enable an ssh-free variant. */ vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol)); if (vt == NULL) { fprintf(stderr, "Internal fault: Unsupported protocol found\n"); return 1; } sk_init(); if (p_WSAEventSelect == NULL) { fprintf(stderr, "Plink requires WinSock 2\n"); return 1; } /* * Plink doesn't provide any way to add forwardings after the * connection is set up, so if there are none now, we can safely set * the "simple" flag. */ if (conf_get_int(conf, CONF_protocol) == PROT_SSH && !conf_get_bool(conf, CONF_x11_forward) && !conf_get_bool(conf, CONF_agentfwd) && !conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) conf_set_bool(conf, CONF_ssh_simple, true); logctx = log_init(default_logpolicy, conf); if (just_test_share_exists) { if (!vt->test_for_upstream) { fprintf(stderr, "Connection sharing not supported for connection " "type '%s'\n", vt->name); return 1; } if (vt->test_for_upstream(conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), conf)) return 0; else return 1; } if (restricted_acl) { lp_eventlog(default_logpolicy, "Running with restricted process ACL"); } /* * Start up the connection. */ netevent = CreateEvent(NULL, false, false, NULL); { const char *error; char *realhost; /* nodelay is only useful if stdin is a character device (console) */ bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) && (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR); error = backend_init(vt, plink_seat, &backend, logctx, conf, conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), &realhost, nodelay, conf_get_bool(conf, CONF_tcp_keepalives)); if (error) { fprintf(stderr, "Unable to open connection:\n%s", error); return 1; } sfree(realhost); } inhandle = GetStdHandle(STD_INPUT_HANDLE); outhandle = GetStdHandle(STD_OUTPUT_HANDLE); errhandle = GetStdHandle(STD_ERROR_HANDLE); /* * Turn off ECHO and LINE input modes. We don't care if this * call fails, because we know we aren't necessarily running in * a console. */ GetConsoleMode(inhandle, &orig_console_mode); SetConsoleMode(inhandle, ENABLE_PROCESSED_INPUT); /* * Pass the output handles to the handle-handling subsystem. * (The input one we leave until we're through the * authentication process.) */ stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL, 0); stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL, 0); handle_sink_init(&stdout_hs, stdout_handle); handle_sink_init(&stderr_hs, stderr_handle); stdout_bs = BinarySink_UPCAST(&stdout_hs); stderr_bs = BinarySink_UPCAST(&stderr_hs); /* * Decide whether to sanitise control sequences out of standard * output and standard error. * * If we weren't given a command-line override, we do this if (a) * the fd in question is pointing at a console, and (b) we aren't * trying to allocate a terminal as part of the session. * * (Rationale: the risk of control sequences is that they cause * confusion when sent to a local console, so if there isn't one, * no problem. Also, if we allocate a remote terminal, then we * sent a terminal type, i.e. we told it what kind of escape * sequences we _like_, i.e. we were expecting to receive some.) */ if (sanitise_stdout == FORCE_ON || (sanitise_stdout == AUTO && is_console_handle(outhandle) && conf_get_bool(conf, CONF_nopty))) { stdout_scc = stripctrl_new(stdout_bs, true, L'\0'); stdout_bs = BinarySink_UPCAST(stdout_scc); } if (sanitise_stderr == FORCE_ON || (sanitise_stderr == AUTO && is_console_handle(errhandle) && conf_get_bool(conf, CONF_nopty))) { stderr_scc = stripctrl_new(stderr_bs, true, L'\0'); stderr_bs = BinarySink_UPCAST(stderr_scc); } main_thread_id = GetCurrentThreadId(); sending = false; now = GETTICKCOUNT(); while (1) { int nhandles; HANDLE *handles; int n; DWORD ticks; if (!sending && backend_sendok(backend)) { stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL, 0); sending = true; } if (toplevel_callback_pending()) { ticks = 0; next = now; } else if (run_timers(now, &next)) { then = now; now = GETTICKCOUNT(); if (now - then > next - then) ticks = 0; else ticks = next - now; } else { ticks = INFINITE; /* no need to initialise next here because we can never * get WAIT_TIMEOUT */ } handles = handle_get_events(&nhandles); handles = sresize(handles, nhandles+1, HANDLE); handles[nhandles] = netevent; n = MsgWaitForMultipleObjects(nhandles+1, handles, false, ticks, QS_POSTMESSAGE); if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) { handle_got_event(handles[n - WAIT_OBJECT_0]); } else if (n == WAIT_OBJECT_0 + nhandles) { WSANETWORKEVENTS things; SOCKET socket; int i, socketstate; /* * We must not call select_result() for any socket * until we have finished enumerating within the tree. * This is because select_result() may close the socket * and modify the tree. */ /* Count the active sockets. */ i = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) i++; /* Expand the buffer if necessary. */ sgrowarray(sklist, sksize, i); /* Retrieve the sockets into sklist. */ skcount = 0; for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; socket = next_socket(&socketstate)) { sklist[skcount++] = socket; } /* Now we're done enumerating; go through the list. */ for (i = 0; i < skcount; i++) { WPARAM wp; socket = sklist[i]; wp = (WPARAM) socket; if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) { static const struct { int bit, mask; } eventtypes[] = { {FD_CONNECT_BIT, FD_CONNECT}, {FD_READ_BIT, FD_READ}, {FD_CLOSE_BIT, FD_CLOSE}, {FD_OOB_BIT, FD_OOB}, {FD_WRITE_BIT, FD_WRITE}, {FD_ACCEPT_BIT, FD_ACCEPT}, }; int e; noise_ultralight(NOISE_SOURCE_IOID, socket); for (e = 0; e < lenof(eventtypes); e++) if (things.lNetworkEvents & eventtypes[e].mask) { LPARAM lp; int err = things.iErrorCode[eventtypes[e].bit]; lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err); select_result(wp, lp); } } } } else if (n == WAIT_OBJECT_0 + nhandles + 1) { 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); } } run_toplevel_callbacks(); if (n == WAIT_TIMEOUT) { now = next; } else { now = GETTICKCOUNT(); } sfree(handles); if (sending) handle_unthrottle(stdin_handle, backend_sendbuffer(backend)); if (!backend_connected(backend) && handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0) break; /* we closed the connection */ } exitcode = backend_exitcode(backend); if (exitcode < 0) { fprintf(stderr, "Remote process exit code unavailable\n"); exitcode = 1; /* this is an error condition */ } cleanup_exit(exitcode); return 0; /* placate compiler warning */ }
static int conf_set_check_multilogin(const char* valstr) { return conf_set_bool(&prefs_conf.check_multilogin,valstr,0); }
static int conf_set_allow_gamelimit(const char* valstr) { return conf_set_bool(&prefs_conf.allow_gamelimit,valstr,0); }
static int conf_setdef_debug(void) { return conf_set_bool(&cmdline_config.debug, NULL, 0); }
static int conf_setdef_console(void) { return conf_set_bool(&cmdline_config.console, NULL, 0); }
static int conf_setdef_foreground(void) { return conf_set_bool(&cmdline_config.foreground, NULL, 0); }
static int conf_set_hide_pass_games(const char* valstr) { return conf_set_bool(&prefs_conf.hide_pass_games,valstr,0); }
static int conf_setdef_ladder_chars_only(void) { return conf_set_bool(&prefs_conf.ladder_chars_only,NULL,0); }
static int conf_setdef_hide_pass_games(void) { return conf_set_bool(&prefs_conf.hide_pass_games,NULL,0); }
static int conf_setdef_gui(void) { return conf_set_bool(&cmdline_config.gui, NULL, 1); }
static int conf_setdef_allow_gamelimit(void) { return conf_set_bool(&prefs_conf.allow_gamelimit,NULL,1); }
int main(int argc, char **argv) { bool sending; int *fdlist; int fd; int i, fdstate; size_t fdsize; int exitcode; bool errors; enum TriState sanitise_stdout = AUTO, sanitise_stderr = AUTO; bool use_subsystem = false; bool just_test_share_exists = false; unsigned long now; struct winsize size; const struct BackendVtable *backvt; fdlist = NULL; fdsize = 0; /* * Initialise port and protocol to sensible defaults. (These * will be overridden by more or less anything.) */ default_protocol = PROT_SSH; default_port = 22; bufchain_init(&stdout_data); bufchain_init(&stderr_data); bufchain_sink_init(&stdout_bcs, &stdout_data); bufchain_sink_init(&stderr_bcs, &stderr_data); stdout_bs = BinarySink_UPCAST(&stdout_bcs); stderr_bs = BinarySink_UPCAST(&stderr_bcs); outgoingeof = EOF_NO; flags = FLAG_STDERR_TTY; cmdline_tooltype |= (TOOLTYPE_HOST_ARG | TOOLTYPE_HOST_ARG_CAN_BE_SESSION | TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX | TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD); stderr_tty_init(); /* * Process the command line. */ conf = conf_new(); do_defaults(NULL, conf); loaded_session = false; default_protocol = conf_get_int(conf, CONF_protocol); default_port = conf_get_int(conf, CONF_port); errors = false; { /* * Override the default protocol if PLINK_PROTOCOL is set. */ char *p = getenv("PLINK_PROTOCOL"); if (p) { const struct BackendVtable *vt = backend_vt_from_name(p); if (vt) { default_protocol = vt->protocol; default_port = vt->default_port; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); } } } while (--argc) { char *p = *++argv; int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL), 1, conf); if (ret == -2) { fprintf(stderr, "plink: option \"%s\" requires an argument\n", p); errors = true; } else if (ret == 2) { --argc, ++argv; } else if (ret == 1) { continue; } else if (!strcmp(p, "-batch")) { console_batch_mode = true; } else if (!strcmp(p, "-s")) { /* Save status to write to conf later. */ use_subsystem = true; } else if (!strcmp(p, "-V") || !strcmp(p, "--version")) { version(); } else if (!strcmp(p, "--help")) { usage(); exit(0); } else if (!strcmp(p, "-pgpfp")) { pgp_fingerprints(); exit(1); } else if (!strcmp(p, "-o")) { if (argc <= 1) { fprintf(stderr, "plink: option \"-o\" requires an argument\n"); errors = true; } else { --argc; /* Explicitly pass "plink" in place of appname for * error reporting purposes. appname will have been * set by be_foo.c to something more generic, probably * "PuTTY". */ provide_xrm_string(*++argv, "plink"); } } else if (!strcmp(p, "-shareexists")) { just_test_share_exists = true; } else if (!strcmp(p, "-fuzznet")) { conf_set_int(conf, CONF_proxy_type, PROXY_FUZZ); conf_set_str(conf, CONF_proxy_telnet_command, "%host"); } else if (!strcmp(p, "-sanitise-stdout") || !strcmp(p, "-sanitize-stdout")) { sanitise_stdout = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stdout") || !strcmp(p, "-no-sanitize-stdout")) { sanitise_stdout = FORCE_OFF; } else if (!strcmp(p, "-sanitise-stderr") || !strcmp(p, "-sanitize-stderr")) { sanitise_stderr = FORCE_ON; } else if (!strcmp(p, "-no-sanitise-stderr") || !strcmp(p, "-no-sanitize-stderr")) { sanitise_stderr = FORCE_OFF; } else if (!strcmp(p, "-no-antispoof")) { console_antispoof_prompt = false; } else if (*p != '-') { strbuf *cmdbuf = strbuf_new(); while (argc > 0) { if (cmdbuf->len > 0) put_byte(cmdbuf, ' '); /* add space separator */ put_datapl(cmdbuf, ptrlen_from_asciz(p)); if (--argc > 0) p = *++argv; } conf_set_str(conf, CONF_remote_cmd, cmdbuf->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ strbuf_free(cmdbuf); break; /* done with cmdline */ } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = true; } } if (errors) return 1; if (!cmdline_host_ok(conf)) { usage(); } prepare_session(conf); /* * Perform command-line overrides on session configuration. */ cmdline_run_saved(conf); /* * If we have no better ideas for the remote username, use the local * one, as 'ssh' does. */ if (conf_get_str(conf, CONF_username)[0] == '\0') { char *user = get_username(); if (user) { conf_set_str(conf, CONF_username, user); sfree(user); } } /* * Apply subsystem status. */ if (use_subsystem) conf_set_bool(conf, CONF_ssh_subsys, true); if (!*conf_get_str(conf, CONF_remote_cmd) && !*conf_get_str(conf, CONF_remote_cmd2) && !*conf_get_str(conf, CONF_ssh_nc_host)) flags |= FLAG_INTERACTIVE; /* * Select protocol. This is farmed out into a table in a * separate file to enable an ssh-free variant. */ backvt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol)); if (!backvt) { fprintf(stderr, "Internal fault: Unsupported protocol found\n"); return 1; } /* * Block SIGPIPE, so that we'll get EPIPE individually on * particular network connections that go wrong. */ putty_signal(SIGPIPE, SIG_IGN); /* * Set up the pipe we'll use to tell us about SIGWINCH. */ if (pipe(signalpipe) < 0) { perror("pipe"); exit(1); } /* We don't want the signal handler to block if the pipe's full. */ nonblock(signalpipe[0]); nonblock(signalpipe[1]); cloexec(signalpipe[0]); cloexec(signalpipe[1]); putty_signal(SIGWINCH, sigwinch); /* * Now that we've got the SIGWINCH handler installed, try to find * out the initial terminal size. */ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &size) >= 0) { conf_set_int(conf, CONF_width, size.ws_col); conf_set_int(conf, CONF_height, size.ws_row); } /* * Decide whether to sanitise control sequences out of standard * output and standard error. * * If we weren't given a command-line override, we do this if (a) * the fd in question is pointing at a terminal, and (b) we aren't * trying to allocate a terminal as part of the session. * * (Rationale: the risk of control sequences is that they cause * confusion when sent to a local terminal, so if there isn't one, * no problem. Also, if we allocate a remote terminal, then we * sent a terminal type, i.e. we told it what kind of escape * sequences we _like_, i.e. we were expecting to receive some.) */ if (sanitise_stdout == FORCE_ON || (sanitise_stdout == AUTO && isatty(STDOUT_FILENO) && conf_get_bool(conf, CONF_nopty))) { stdout_scc = stripctrl_new(stdout_bs, true, L'\0'); stdout_bs = BinarySink_UPCAST(stdout_scc); } if (sanitise_stderr == FORCE_ON || (sanitise_stderr == AUTO && isatty(STDERR_FILENO) && conf_get_bool(conf, CONF_nopty))) { stderr_scc = stripctrl_new(stderr_bs, true, L'\0'); stderr_bs = BinarySink_UPCAST(stderr_scc); } sk_init(); uxsel_init(); /* * Plink doesn't provide any way to add forwardings after the * connection is set up, so if there are none now, we can safely set * the "simple" flag. */ if (conf_get_int(conf, CONF_protocol) == PROT_SSH && !conf_get_bool(conf, CONF_x11_forward) && !conf_get_bool(conf, CONF_agentfwd) && !conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) conf_set_bool(conf, CONF_ssh_simple, true); if (just_test_share_exists) { if (!backvt->test_for_upstream) { fprintf(stderr, "Connection sharing not supported for connection " "type '%s'\n", backvt->name); return 1; } if (backvt->test_for_upstream(conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), conf)) return 0; else return 1; } /* * Start up the connection. */ logctx = log_init(default_logpolicy, conf); { const char *error; char *realhost; /* nodelay is only useful if stdin is a terminal device */ bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) && isatty(0); /* This is a good place for a fuzzer to fork us. */ #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); #endif error = backend_init(backvt, plink_seat, &backend, logctx, conf, conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), &realhost, nodelay, conf_get_bool(conf, CONF_tcp_keepalives)); if (error) { fprintf(stderr, "Unable to open connection:\n%s\n", error); return 1; } ldisc_create(conf, NULL, backend, plink_seat); sfree(realhost); } /* * Set up the initial console mode. We don't care if this call * fails, because we know we aren't necessarily running in a * console. */ local_tty = (tcgetattr(STDIN_FILENO, &orig_termios) == 0); atexit(cleanup_termios); seat_echoedit_update(plink_seat, 1, 1); sending = false; now = GETTICKCOUNT(); pollwrapper *pw = pollwrap_new(); while (1) { int rwx; int ret; unsigned long next; pollwrap_clear(pw); pollwrap_add_fd_rwx(pw, signalpipe[0], SELECT_R); if (!sending && backend_connected(backend) && backend_sendok(backend) && backend_sendbuffer(backend) < MAX_STDIN_BACKLOG) { /* If we're OK to send, then try to read from stdin. */ pollwrap_add_fd_rwx(pw, STDIN_FILENO, SELECT_R); } if (bufchain_size(&stdout_data) > 0) { /* If we have data for stdout, try to write to stdout. */ pollwrap_add_fd_rwx(pw, STDOUT_FILENO, SELECT_W); } if (bufchain_size(&stderr_data) > 0) { /* If we have data for stderr, try to write to stderr. */ pollwrap_add_fd_rwx(pw, STDERR_FILENO, SELECT_W); } /* Count the currently active fds. */ i = 0; for (fd = first_fd(&fdstate, &rwx); fd >= 0; fd = next_fd(&fdstate, &rwx)) i++; /* Expand the fdlist buffer if necessary. */ sgrowarray(fdlist, fdsize, i); /* * Add all currently open fds to pw, and store them in fdlist * as well. */ int fdcount = 0; for (fd = first_fd(&fdstate, &rwx); fd >= 0; fd = next_fd(&fdstate, &rwx)) { fdlist[fdcount++] = fd; pollwrap_add_fd_rwx(pw, fd, rwx); } if (toplevel_callback_pending()) { ret = pollwrap_poll_instant(pw); } else if (run_timers(now, &next)) { do { unsigned long then; long ticks; then = now; now = GETTICKCOUNT(); if (now - then > next - then) ticks = 0; else ticks = next - now; bool overflow = false; if (ticks > INT_MAX) { ticks = INT_MAX; overflow = true; } ret = pollwrap_poll_timeout(pw, ticks); if (ret == 0 && !overflow) now = next; else now = GETTICKCOUNT(); } while (ret < 0 && errno == EINTR); } else { ret = pollwrap_poll_endless(pw); } if (ret < 0 && errno == EINTR) continue; if (ret < 0) { perror("poll"); exit(1); } for (i = 0; i < fdcount; i++) { fd = fdlist[i]; int rwx = pollwrap_get_fd_rwx(pw, fd); /* * We must process exceptional notifications before * ordinary readability ones, or we may go straight * past the urgent marker. */ if (rwx & SELECT_X) select_result(fd, SELECT_X); if (rwx & SELECT_R) select_result(fd, SELECT_R); if (rwx & SELECT_W) select_result(fd, SELECT_W); } if (pollwrap_check_fd_rwx(pw, signalpipe[0], SELECT_R)) { char c[1]; struct winsize size; if (read(signalpipe[0], c, 1) <= 0) /* ignore error */; /* ignore its value; it'll be `x' */ if (ioctl(STDIN_FILENO, TIOCGWINSZ, (void *)&size) >= 0) backend_size(backend, size.ws_col, size.ws_row); } if (pollwrap_check_fd_rwx(pw, STDIN_FILENO, SELECT_R)) { char buf[4096]; int ret; if (backend_connected(backend)) { ret = read(STDIN_FILENO, buf, sizeof(buf)); noise_ultralight(NOISE_SOURCE_IOLEN, ret); if (ret < 0) { perror("stdin: read"); exit(1); } else if (ret == 0) { backend_special(backend, SS_EOF, 0); sending = false; /* send nothing further after this */ } else { if (local_tty) from_tty(buf, ret); else backend_send(backend, buf, ret); } } } if (pollwrap_check_fd_rwx(pw, STDOUT_FILENO, SELECT_W)) { backend_unthrottle(backend, try_output(false)); } if (pollwrap_check_fd_rwx(pw, STDERR_FILENO, SELECT_W)) { backend_unthrottle(backend, try_output(true)); } run_toplevel_callbacks(); if (!backend_connected(backend) && bufchain_size(&stdout_data) == 0 && bufchain_size(&stderr_data) == 0) break; /* we closed the connection */ } exitcode = backend_exitcode(backend); if (exitcode < 0) { fprintf(stderr, "Remote process exit code unavailable\n"); exitcode = 1; /* this is an error condition */ } cleanup_exit(exitcode); return exitcode; /* shouldn't happen, but placates gcc */ }
static int conf_setdef_check_multilogin(void) { return conf_set_bool(&prefs_conf.check_multilogin,NULL,1); }
int cmdline_process_param(const char *p, char *value, int need_save, Conf *conf) { int ret = 0; if (p[0] != '-') { if (need_save < 0) return 0; /* * Common handling for the tools whose initial command-line * arguments specify a hostname to connect to, i.e. PuTTY and * Plink. Doesn't count the file transfer tools, because their * hostname specification appears as part of a more * complicated scheme. */ if ((cmdline_tooltype & TOOLTYPE_HOST_ARG) && !seen_hostname_argument && (!(cmdline_tooltype & TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD) || !loaded_session || !conf_launchable(conf))) { /* * Treat this argument as a host name, if we have not yet * seen a host name argument or -load. * * Exception, in some tools (Plink): if we have seen -load * but it didn't create a launchable session, then we * still accept a hostname argument following that -load. * This allows you to make saved sessions that configure * lots of other stuff (colour schemes, terminal settings * etc) and then say 'putty -load sessionname hostname'. * * Also, we carefully _don't_ test conf for launchability * if we haven't been explicitly told to load a session * (otherwise saving a host name into Default Settings * would cause 'putty' on its own to immediately launch * the default session and never be able to do anything * else). */ if (!strncmp(p, "telnet:", 7)) { /* * If the argument starts with "telnet:", set the * protocol to Telnet and process the string as a * Telnet URL. */ /* * Skip the "telnet:" or "telnet://" prefix. */ p += 7; if (p[0] == '/' && p[1] == '/') p += 2; conf_set_int(conf, CONF_protocol, PROT_TELNET); /* * The next thing we expect is a host name. */ { const char *host = p; char *buf; p += host_strcspn(p, ":/"); buf = dupprintf("%.*s", (int)(p - host), host); conf_set_str(conf, CONF_host, buf); sfree(buf); seen_hostname_argument = true; } /* * If the host name is followed by a colon, then * expect a port number after it. */ if (*p == ':') { p++; conf_set_int(conf, CONF_port, atoi(p)); /* * Set the flag that will stop us from treating * the next argument as a separate port; this one * counts as explicitly provided. */ seen_port_argument = true; } else { conf_set_int(conf, CONF_port, -1); } } else { char *user = NULL, *hostname = NULL; const char *hostname_after_user; int port_override = -1; size_t len; /* * Otherwise, treat it as a bare host name. */ if (cmdline_tooltype & TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX) { /* * Here Plink checks for a comma-separated * protocol prefix, e.g. 'ssh,hostname' or * 'ssh,user@hostname'. * * I'm not entirely sure why; this behaviour dates * from 2000 and isn't explained. But I _think_ it * has to do with CVS transport or similar use * cases, in which the end user invokes the SSH * client indirectly, via some means that only * lets them pass a single string argument, and it * was occasionally useful to shoehorn the choice * of protocol into that argument. */ const char *comma = strchr(p, ','); if (comma) { char *prefix = dupprintf("%.*s", (int)(comma - p), p); const struct BackendVtable *vt = backend_vt_from_name(prefix); if (vt) { default_protocol = vt->protocol; conf_set_int(conf, CONF_protocol, default_protocol); port_override = vt->default_port; } else { cmdline_error("unrecognised protocol prefix '%s'", prefix); } sfree(prefix); p = comma + 1; } } hostname_after_user = p; if (cmdline_tooltype & TOOLTYPE_HOST_ARG_CAN_BE_SESSION) { /* * If the hostname argument can also be a saved * session (see below), then here we also check * for a user@ prefix, which will override the * username from the saved session. * * (If the hostname argument _isn't_ a saved * session, we don't do this.) */ const char *at = strrchr(p, '@'); if (at) { user = dupprintf("%.*s", (int)(at - p), p); hostname_after_user = at + 1; } } /* * Write the whole hostname argument (minus only that * optional protocol prefix) into the existing Conf, * for tools that don't treat it as a saved session * and as a fallback for those that do. */ hostname = dupstr(p + strspn(p, " \t")); len = strlen(hostname); while (len > 0 && (hostname[len-1] == ' ' || hostname[len-1] == '\t')) hostname[--len] = '\0'; seen_hostname_argument = true; conf_set_str(conf, CONF_host, hostname); if ((cmdline_tooltype & TOOLTYPE_HOST_ARG_CAN_BE_SESSION) && !loaded_session) { /* * For some tools, we equivocate between a * hostname argument and an argument naming a * saved session. Here we attempt to load a * session with the specified name, and if that * session exists and is launchable, we overwrite * the entire Conf with it. * * We skip this check if a -load option has * already happened, so that * * plink -load non-launchable-session hostname * * will treat 'hostname' as a hostname _even_ if a * saved session called 'hostname' exists. (This * doesn't lose any functionality someone could * have needed, because if 'hostname' did cause a * session to be loaded, then it would overwrite * everything from the previously loaded session. * So if that was the behaviour someone wanted, * then they could get it by leaving off the * -load completely.) */ Conf *conf2 = conf_new(); if (do_defaults(hostname_after_user, conf2) && conf_launchable(conf2)) { conf_copy_into(conf, conf2); loaded_session = true; /* And override the username if one was given. */ if (user) conf_set_str(conf, CONF_username, user); } conf_free(conf2); } sfree(hostname); sfree(user); if (port_override >= 0) conf_set_int(conf, CONF_port, port_override); } return 1; } else if ((cmdline_tooltype & TOOLTYPE_PORT_ARG) && !seen_port_argument) { /* * If we've already got a host name from the command line * (either as a hostname argument or a qualifying -load), * but not a port number, then treat the next argument as * a port number. * * We handle this by calling ourself recursively to * pretend we received a -P argument, so that it will be * deferred until it's a good moment to run it. */ char *dup = dupstr(p); /* 'value' is not a const char * */ int retd = cmdline_process_param("-P", dup, 1, conf); sfree(dup); assert(retd == 2); seen_port_argument = true; return 1; } else { /* * Refuse to recognise this argument, and give it back to * the tool's own command-line processing. */ return 0; } } #ifdef PUTTYNG if (!stricmp(p, "-hwndparent")) { RETURN(2); hwnd_parent = atoi(value); return 2; } #endif if (!strcmp(p, "-load")) { RETURN(2); /* This parameter must be processed immediately rather than being * saved. */ do_defaults(value, conf); loaded_session = true; cmdline_session_name = dupstr(value); return 2; } if (!strcmp(p, "-ssh")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_SSH; default_port = 22; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); return 1; } if (!strcmp(p, "-telnet")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_TELNET; default_port = 23; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); return 1; } if (!strcmp(p, "-rlogin")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_RLOGIN; default_port = 513; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); return 1; } if (!strcmp(p, "-raw")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_RAW; conf_set_int(conf, CONF_protocol, default_protocol); } if (!strcmp(p, "-serial")) { RETURN(1); /* Serial is not NONNETWORK in an odd sense of the word */ UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_SERIAL; conf_set_int(conf, CONF_protocol, default_protocol); /* The host parameter will already be loaded into CONF_host, * so copy it across */ conf_set_str(conf, CONF_serline, conf_get_str(conf, CONF_host)); } if (!strcmp(p, "-v")) { RETURN(1); flags |= FLAG_VERBOSE; } if (!strcmp(p, "-l")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_str(conf, CONF_username, value); } if (!strcmp(p, "-loghost")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_str(conf, CONF_loghost, value); } if (!strcmp(p, "-hostkey")) { char *dup; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); dup = dupstr(value); if (!validate_manual_hostkey(dup)) { cmdline_error("'%s' is not a valid format for a manual host " "key specification", value); sfree(dup); return ret; } conf_set_str_str(conf, CONF_ssh_manual_hostkeys, dup, ""); sfree(dup); } if ((!strcmp(p, "-L") || !strcmp(p, "-R") || !strcmp(p, "-D"))) { char type, *q, *qq, *key, *val; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); if (strcmp(p, "-D")) { /* * For -L or -R forwarding types: * * We expect _at least_ two colons in this string. The * possible formats are `sourceport:desthost:destport', * or `sourceip:sourceport:desthost:destport' if you're * specifying a particular loopback address. We need to * replace the one between source and dest with a \t; * this means we must find the second-to-last colon in * the string. * * (This looks like a foolish way of doing it given the * existence of strrchr, but it's more efficient than * two strrchrs - not to mention that the second strrchr * would require us to modify the input string!) */ type = p[1]; /* 'L' or 'R' */ q = qq = host_strchr(value, ':'); while (qq) { char *qqq = host_strchr(qq+1, ':'); if (qqq) q = qq; qq = qqq; } if (!q) { cmdline_error("-%c expects at least two colons in its" " argument", type); return ret; } key = dupprintf("%c%.*s", type, (int)(q - value), value); val = dupstr(q+1); } else { /* * Dynamic port forwardings are entered under the same key * as if they were local (because they occupy the same * port space - a local and a dynamic forwarding on the * same local port are mutually exclusive), with the * special value "D" (which can be distinguished from * anything in the ordinary -L case by containing no * colon). */ key = dupprintf("L%s", value); val = dupstr("D"); } conf_set_str_str(conf, CONF_portfwd, key, val); sfree(key); sfree(val); } if ((!strcmp(p, "-nc"))) { char *host, *portp; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); portp = host_strchr(value, ':'); if (!portp) { cmdline_error("-nc expects argument of form 'host:port'"); return ret; } host = dupprintf("%.*s", (int)(portp - value), value); conf_set_str(conf, CONF_ssh_nc_host, host); conf_set_int(conf, CONF_ssh_nc_port, atoi(portp + 1)); sfree(host); } if (!strcmp(p, "-m")) { const char *filename; FILE *fp; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); filename = value; fp = fopen(filename, "r"); if (!fp) { cmdline_error("unable to open command file \"%s\"", filename); return ret; } strbuf *command = strbuf_new(); char readbuf[4096]; while (1) { size_t nread = fread(readbuf, 1, sizeof(readbuf), fp); if (nread == 0) break; put_data(command, readbuf, nread); } fclose(fp); conf_set_str(conf, CONF_remote_cmd, command->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no terminal */ strbuf_free(command); } if (!strcmp(p, "-P")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(1); /* lower priority than -ssh,-telnet */ conf_set_int(conf, CONF_port, atoi(value)); } if (!strcmp(p, "-pw")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(1); /* We delay evaluating this until after the protocol is decided, * so that we can warn if it's of no use with the selected protocol */ if (conf_get_int(conf, CONF_protocol) != PROT_SSH) cmdline_error("the -pw option can only be used with the " "SSH protocol"); else { cmdline_password = dupstr(value); /* Assuming that `value' is directly from argv, make a good faith * attempt to trample it, to stop it showing up in `ps' output * on Unix-like systems. Not guaranteed, of course. */ smemclr(value, strlen(value)); } } if (!strcmp(p, "-agent") || !strcmp(p, "-pagent") || !strcmp(p, "-pageant")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_tryagent, true); } if (!strcmp(p, "-noagent") || !strcmp(p, "-nopagent") || !strcmp(p, "-nopageant")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_tryagent, false); } if (!strcmp(p, "-share")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_ssh_connection_sharing, true); } if (!strcmp(p, "-noshare")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_ssh_connection_sharing, false); } if (!strcmp(p, "-A")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_agentfwd, true); } if (!strcmp(p, "-a")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_agentfwd, false); } if (!strcmp(p, "-X")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_x11_forward, true); } if (!strcmp(p, "-x")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_x11_forward, false); } if (!strcmp(p, "-t")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(1); /* lower priority than -m */ conf_set_bool(conf, CONF_nopty, false); } if (!strcmp(p, "-T")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(1); conf_set_bool(conf, CONF_nopty, true); } if (!strcmp(p, "-N")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_ssh_no_shell, true); } if (!strcmp(p, "-C")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_compression, true); } if (!strcmp(p, "-1")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_int(conf, CONF_sshprot, 0); /* ssh protocol 1 only */ } if (!strcmp(p, "-2")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_int(conf, CONF_sshprot, 3); /* ssh protocol 2 only */ } if (!strcmp(p, "-i")) { Filename *fn; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); fn = filename_from_str(value); conf_set_filename(conf, CONF_keyfile, fn); filename_free(fn); } if (!strcmp(p, "-4") || !strcmp(p, "-ipv4")) { RETURN(1); SAVEABLE(1); conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV4); } if (!strcmp(p, "-6") || !strcmp(p, "-ipv6")) { RETURN(1); SAVEABLE(1); conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV6); } if (!strcmp(p, "-sercfg")) { char* nextitem; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(1); if (conf_get_int(conf, CONF_protocol) != PROT_SERIAL) cmdline_error("the -sercfg option can only be used with the " "serial protocol"); /* Value[0] contains one or more , separated values, like 19200,8,n,1,X */ nextitem = value; while (nextitem[0] != '\0') { int length, skip; char *end = strchr(nextitem, ','); if (!end) { length = strlen(nextitem); skip = 0; } else { length = end - nextitem; nextitem[length] = '\0'; skip = 1; } if (length == 1) { switch (*nextitem) { case '1': case '2': conf_set_int(conf, CONF_serstopbits, 2 * (*nextitem-'0')); break; case '5': case '6': case '7': case '8': case '9': conf_set_int(conf, CONF_serdatabits, *nextitem-'0'); break; case 'n': conf_set_int(conf, CONF_serparity, SER_PAR_NONE); break; case 'o': conf_set_int(conf, CONF_serparity, SER_PAR_ODD); break; case 'e': conf_set_int(conf, CONF_serparity, SER_PAR_EVEN); break; case 'm': conf_set_int(conf, CONF_serparity, SER_PAR_MARK); break; case 's': conf_set_int(conf, CONF_serparity, SER_PAR_SPACE); break; case 'N': conf_set_int(conf, CONF_serflow, SER_FLOW_NONE); break; case 'X': conf_set_int(conf, CONF_serflow, SER_FLOW_XONXOFF); break; case 'R': conf_set_int(conf, CONF_serflow, SER_FLOW_RTSCTS); break; case 'D': conf_set_int(conf, CONF_serflow, SER_FLOW_DSRDTR); break; default: cmdline_error("Unrecognised suboption \"-sercfg %c\"", *nextitem); } } else if (length == 3 && !strncmp(nextitem,"1.5",3)) { /* Messy special case */ conf_set_int(conf, CONF_serstopbits, 3); } else { int serspeed = atoi(nextitem); if (serspeed != 0) { conf_set_int(conf, CONF_serspeed, serspeed); } else { cmdline_error("Unrecognised suboption \"-sercfg %s\"", nextitem); } } nextitem += length + skip; } } if (!strcmp(p, "-sessionlog")) { Filename *fn; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER); /* but available even in TOOLTYPE_NONNETWORK, cf pterm "-log" */ SAVEABLE(0); fn = filename_from_str(value); conf_set_filename(conf, CONF_logfilename, fn); conf_set_int(conf, CONF_logtype, LGTYP_DEBUG); filename_free(fn); } if (!strcmp(p, "-sshlog") || !strcmp(p, "-sshrawlog")) { Filename *fn; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); fn = filename_from_str(value); conf_set_filename(conf, CONF_logfilename, fn); conf_set_int(conf, CONF_logtype, !strcmp(p, "-sshlog") ? LGTYP_PACKETS : /* !strcmp(p, "-sshrawlog") ? */ LGTYP_SSHRAW); filename_free(fn); } if (!strcmp(p, "-proxycmd")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_int(conf, CONF_proxy_type, PROXY_CMD); conf_set_str(conf, CONF_proxy_telnet_command, value); } #ifdef _WINDOWS /* * Cross-tool options only available on Windows. */ if (!strcmp(p, "-restrict-acl") || !strcmp(p, "-restrict_acl") || !strcmp(p, "-restrictacl")) { RETURN(1); restrict_process_acl(); restricted_acl = true; } #endif return ret; /* unrecognised */ }
void menu_request_settings(void) { gint result; GtkDialog * dialog; GtkToggleButton * autostart_studio_button; GtkToggleButton * send_notifications_button; GtkEntry * shell_entry; GtkEntry * terminal_entry; GtkSpinButton * js_delay_spin; GtkEntry * jack_conf_tool_entry; bool autostart; bool notify; const char * shell; const char * terminal; unsigned int js_delay; const char * jack_conf_tool; autostart_studio_button = GTK_TOGGLE_BUTTON(get_gtk_builder_widget("settings_studio_autostart_checkbutton")); send_notifications_button = GTK_TOGGLE_BUTTON(get_gtk_builder_widget("settings_send_notifications_checkbutton")); shell_entry = GTK_ENTRY(get_gtk_builder_widget("settings_shell_entry")); terminal_entry = GTK_ENTRY(get_gtk_builder_widget("settings_terminal_entry")); js_delay_spin = GTK_SPIN_BUTTON(get_gtk_builder_widget("settings_js_delay_spin")); jack_conf_tool_entry = GTK_ENTRY(get_gtk_builder_widget("settings_jack_conf_tool_entry")); dialog = GTK_DIALOG(get_gtk_builder_widget("settings_dialog")); if (!conf_get_bool(LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART, &autostart)) { autostart = LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART_DEFAULT; } if (!conf_get_bool(LADISH_CONF_KEY_DAEMON_NOTIFY, ¬ify)) { notify = LADISH_CONF_KEY_DAEMON_NOTIFY_DEFAULT; } if (!conf_get(LADISH_CONF_KEY_DAEMON_SHELL, &shell)) { shell = LADISH_CONF_KEY_DAEMON_SHELL_DEFAULT; } if (!conf_get(LADISH_CONF_KEY_DAEMON_TERMINAL, &terminal)) { terminal = LADISH_CONF_KEY_DAEMON_TERMINAL_DEFAULT; } if (!conf_get_uint(LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY, &js_delay)) { js_delay = LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY_DEFAULT; } if (!conf_get(LADISH_CONF_KEY_JACK_CONF_TOOL, &jack_conf_tool)) { jack_conf_tool = LADISH_CONF_KEY_JACK_CONF_TOOL_DEFAULT; } gtk_toggle_button_set_active(autostart_studio_button, autostart); gtk_toggle_button_set_active(send_notifications_button, notify); gtk_entry_set_text(shell_entry, shell); gtk_entry_set_text(terminal_entry, terminal); gtk_entry_set_text(jack_conf_tool_entry, jack_conf_tool); gtk_spin_button_set_range(js_delay_spin, 0, 1000); gtk_spin_button_set_increments(js_delay_spin, 1, 2); gtk_spin_button_set_value(js_delay_spin, js_delay); gtk_widget_show(GTK_WIDGET(dialog)); result = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_hide(GTK_WIDGET(dialog)); if (result != GTK_RESPONSE_OK) { return; } autostart = gtk_toggle_button_get_active(autostart_studio_button); notify = gtk_toggle_button_get_active(send_notifications_button); shell = gtk_entry_get_text(shell_entry); terminal = gtk_entry_get_text(terminal_entry); js_delay = gtk_spin_button_get_value(js_delay_spin); jack_conf_tool = gtk_entry_get_text(jack_conf_tool_entry); if (!conf_set_bool(LADISH_CONF_KEY_DAEMON_STUDIO_AUTOSTART, autostart) || !conf_set_bool(LADISH_CONF_KEY_DAEMON_NOTIFY, notify) || !conf_set(LADISH_CONF_KEY_DAEMON_SHELL, shell) || !conf_set(LADISH_CONF_KEY_DAEMON_TERMINAL, terminal) || !conf_set_uint(LADISH_CONF_KEY_DAEMON_JS_SAVE_DELAY, js_delay) || !conf_set(LADISH_CONF_KEY_JACK_CONF_TOOL, jack_conf_tool)) { error_message_box(_("Storing settings")); } }
static int conf_set_ladder_chars_only(const char * valstr) { return conf_set_bool(&prefs_conf.ladder_chars_only,valstr,0); }