void ErrorDialog::error (const String& msg) { cmdline_error (msg); messages.push_back (ErrorMsg (1, msg)); if (idle_connection.empty()) idle_connection = Glib::signal_idle().connect (sigc::ptr_fun (&display_errors)); }
static bool cmdline_check_unavailable(int flag, const char *p) { if (cmdline_tooltype & flag) { cmdline_error("option \"%s\" not available in this tool", p); return true; } return false; }
int do_cmdline(int argc, char **argv, int do_everything, int *allow_launch, struct gui_data *inst, Conf *conf) { int err = 0; char *val; /* * Macros to make argument handling easier. Note that because * they need to call `continue', they cannot be contained in * the usual do {...} while (0) wrapper to make them * syntactically single statements; hence it is not legal to * use one of these macros as an unbraced statement between * `if' and `else'. */ #define EXPECTS_ARG { \ if (--argc <= 0) { \ err = 1; \ fprintf(stderr, "%s: %s expects an argument\n", appname, p); \ continue; \ } else \ val = *++argv; \ } #define SECOND_PASS_ONLY { if (!do_everything) continue; } while (--argc > 0) { char *p = *++argv; int ret; /* * Shameless cheating. Debian requires all X terminal * emulators to support `-T title'; but * cmdline_process_param will eat -T (it means no-pty) and * complain that pterm doesn't support it. So, in pterm * only, we convert -T into -title. */ if ((cmdline_tooltype & TOOLTYPE_NONNETWORK) && !strcmp(p, "-T")) p = (char*)"-title"; ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL), do_everything ? 1 : -1, conf); if (ret == -2) { cmdline_error("option \"%s\" requires an argument",p); } else if (ret == 2) { --argc, ++argv; /* skip next argument */ continue; } else if (ret == 1) { continue; } if (!strcmp(p, "-fn") || !strcmp(p, "-font")) { FontSpec *fs; EXPECTS_ARG; SECOND_PASS_ONLY; fs = fontspec_new(val); conf_set_fontspec(conf, CONF_font, fs); fontspec_free(fs); } else if (!strcmp(p, "-fb")) { FontSpec *fs; EXPECTS_ARG; SECOND_PASS_ONLY; fs = fontspec_new(val); conf_set_fontspec(conf, CONF_boldfont, fs); fontspec_free(fs); } else if (!strcmp(p, "-fw")) { FontSpec *fs; EXPECTS_ARG; SECOND_PASS_ONLY; fs = fontspec_new(val); conf_set_fontspec(conf, CONF_widefont, fs); fontspec_free(fs); } else if (!strcmp(p, "-fwb")) { FontSpec *fs; EXPECTS_ARG; SECOND_PASS_ONLY; fs = fontspec_new(val); conf_set_fontspec(conf, CONF_wideboldfont, fs); fontspec_free(fs); } else if (!strcmp(p, "-cs")) { EXPECTS_ARG; SECOND_PASS_ONLY; conf_set_str(conf, CONF_line_codepage, val); } else if (!strcmp(p, "-geometry")) { #ifdef Q_OS_UNIX int flags, x, y; unsigned int w, h; EXPECTS_ARG; SECOND_PASS_ONLY; flags = XParseGeometry(val, &x, &y, &w, &h); if (flags & WidthValue) conf_set_int(conf, CONF_width, w); if (flags & HeightValue) conf_set_int(conf, CONF_height, h); if (flags & (XValue | YValue)) { inst->xpos = x; inst->ypos = y; inst->gotpos = TRUE; inst->gravity = ((flags & XNegative ? 1 : 0) | (flags & YNegative ? 2 : 0)); } #endif } else if (!strcmp(p, "-sl")) { EXPECTS_ARG; SECOND_PASS_ONLY; conf_set_int(conf, CONF_savelines, atoi(val)); } /*else if (!strcmp(p, "-fg") || !strcmp(p, "-bg") || !strcmp(p, "-bfg") || !strcmp(p, "-bbg") || !strcmp(p, "-cfg") || !strcmp(p, "-cbg")) { GdkColor col; EXPECTS_ARG; SECOND_PASS_ONLY; if (!gdk_color_parse(val, &col)) { err = 1; fprintf(stderr, "%s: unable to parse colour \"%s\"\n", appname, val); } else { int index; index = (!strcmp(p, "-fg") ? 0 : !strcmp(p, "-bg") ? 2 : !strcmp(p, "-bfg") ? 1 : !strcmp(p, "-bbg") ? 3 : !strcmp(p, "-cfg") ? 4 : !strcmp(p, "-cbg") ? 5 : -1); assert(index != -1); cfg->colours[index][0] = col.red / 256; cfg->colours[index][1] = col.green / 256; cfg->colours[index][2] = col.blue / 256; } } */else if (use_pty_argv && !strcmp(p, "-e")) { /* This option swallows all further arguments. */ if (!do_everything) break; if (--argc > 0) { int i; pty_argv = snewn(argc+1, char *); ++argv; for (i = 0; i < argc; i++) pty_argv[i] = argv[i]; pty_argv[argc] = NULL; break; /* finished command-line processing */ } else err = 1, fprintf(stderr, "%s: -e expects an argument\n", appname); } else if (!strcmp(p, "-title")) {
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 */ }
/* * Process the command line. */ void CmdLineHandler::process_cmdline(LPSTR cmdline) { USES_CONVERSION; char *p; int got_host = 0; /* By default, we bring up the config dialog, rather than launching * a session. This gets set to TRUE if something happens to change * that (e.g., a hostname is specified on the command-line). */ int allow_launch = FALSE; default_protocol = be_default_protocol; /* Find the appropriate default port. */ { Backend *b = backend_from_proto(default_protocol); default_port = 0; /* illegal */ if (b) default_port = b->default_port; } cfg.logtype = LGTYP_NONE; do_defaults(NULL, &cfg); p = cmdline; /* * Process a couple of command-line options which are more * easily dealt with before the line is broken up into words. * These are the old-fashioned but convenient @sessionname and * the internal-use-only &sharedmemoryhandle, neither of which * are combined with anything else. */ while (*p && isspace(*p)) p++; if (*p == '@') { /* * An initial @ means that the whole of the rest of the * command line should be treated as the name of a saved * session, with _no quoting or escaping_. This makes it a * very convenient means of automated saved-session * launching, via IDM_SAVEDSESS or Windows 7 jump lists. */ int i = strlen(p); while (i > 1 && isspace(p[i - 1])) i--; p[i] = '\0'; do_defaults(p + 1, &cfg); if (!cfg_launchable(&cfg) && !do_config()) { return; } allow_launch = TRUE; /* allow it to be launched directly */ } else if (*p == '&') { /* * An initial & means we've been given a command line * containing the hex value of a HANDLE for a file * mapping object, which we must then extract as a * config. */ HANDLE filemap; Config *cp; if (sscanf(p + 1, "%p", &filemap) == 1 && (cp = (Config*)MapViewOfFile(filemap, FILE_MAP_READ, 0, 0, sizeof(Config))) != NULL) { cfg = *cp; UnmapViewOfFile(cp); CloseHandle(filemap); } else if (!do_config()) { cleanup_exit(0); } allow_launch = TRUE; } else { /* * Otherwise, break up the command line and deal with * it sensibly. */ int argc, i; char **argv; split_into_argv(cmdline, &argc, &argv, NULL); for (i = 0; i < argc; i++) { char *p = argv[i]; int ret; ret = cmdline_process_param(p, i+1<argc?argv[i+1]:NULL, 1, &cfg); if (ret == -2) { cmdline_error("option \"%s\" requires an argument", p); } else if (ret == 2) { i++; /* skip next argument */ } else if (ret == 1) { continue; /* nothing further needs doing */ } else if (!strcmp(p, "-cleanup") || !strcmp(p, "-cleanup-during-uninstall")) { /* * `putty -cleanup'. Remove all registry * entries associated with PuTTY, and also find * and delete the random seed file. */ char *s1, *s2; /* Are we being invoked from an uninstaller? */ if (!strcmp(p, "-cleanup-during-uninstall")) { s1 = dupprintf("Remove saved sessions and random seed file?\n" "\n" "If you hit Yes, ALL Registry entries associated\n" "with %s will be removed, as well as the\n" "random seed file. THIS PROCESS WILL\n" "DESTROY YOUR SAVED SESSIONS.\n" "(This only affects the currently logged-in user.)\n" "\n" "If you hit No, uninstallation will proceed, but\n" "saved sessions etc will be left on the machine.", appname); s2 = dupprintf("%s Uninstallation", appname); } else { s1 = dupprintf("This procedure will remove ALL Registry entries\n" "associated with %s, and will also remove\n" "the random seed file. (This only affects the\n" "currently logged-in user.)\n" "\n" "THIS PROCESS WILL DESTROY YOUR SAVED SESSIONS.\n" "Are you really sure you want to continue?", appname); s2 = dupprintf("%s Warning", appname); } //if (message_box(A2W(s1), A2W(s2), // MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2, // HELPCTXID(option_cleanup)) == IDYES) { if (MessageBox(WindowInterface::GetInstance()->getNativeTopWnd(), A2W(s1), A2W(s2), MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDYES) { gStorage->cleanup_all(); } sfree(s1); sfree(s2); exit(0); } else if (!strcmp(p, "-pgpfp")) { pgp_fingerprints(); exit(1); } else if (*p != '-') { char *q = p; if (got_host) { /* * If we already have a host name, treat * this argument as a port number. NB we * have to treat this as a saved -P * argument, so that it will be deferred * until it's a good moment to run it. */ int ret = cmdline_process_param("-P", p, 1, &cfg); assert(ret == 2); } else if (!strncmp(q, "telnet:", 7)) { /* * If the hostname starts with "telnet:", * set the protocol to Telnet and process * the string as a Telnet URL. */ char c; q += 7; if (q[0] == '/' && q[1] == '/') q += 2; cfg.protocol = PROT_TELNET; p = q; while (*p && *p != ':' && *p != '/') p++; c = *p; if (*p) *p++ = '\0'; if (c == ':') cfg.port = atoi(p); else cfg.port = -1; strncpy(cfg.host, q, sizeof(cfg.host) - 1); cfg.host[sizeof(cfg.host) - 1] = '\0'; got_host = 1; } else { /* * Otherwise, treat this argument as a host * name. */ while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; strncpy(cfg.host, q, sizeof(cfg.host) - 1); cfg.host[sizeof(cfg.host) - 1] = '\0'; got_host = 1; } } else { cmdline_error("unknown option \"%s\"", p); } } } cmdline_run_saved(&cfg); if (loaded_session || got_host) allow_launch = TRUE; if ((!allow_launch || !cfg_launchable(&cfg)) && !do_config()) { return ; } adjust_host(&cfg); if (!strcmp(cfg.session_name, DEFAULT_SESSION_NAME)){ if (cfg.protocol == PROT_SERIAL) snprintf(cfg.session_name, sizeof(cfg.session_name), "tmp#%s:%d", cfg.serline, cfg.serspeed); else snprintf(cfg.session_name, sizeof(cfg.session_name), "tmp#%s:%d", cfg.host, cfg.port); save_settings(cfg.session_name, &cfg); } }