int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { int argc; char **argv; split_into_argv(cmdline, &argc, &argv, NULL); if (argc > 0) { /* * Assume the first argument to be a private key file, and * attempt to load it. */ cmdline_keyfile = argv[0]; } InitCommonControls(); hinst = inst; /* * See if we can find our Help file. */ { char b[2048], *p, *q, *r; FILE *fp; GetModuleFileName(NULL, b, sizeof(b) - 1); r = b; p = strrchr(b, '\\'); if (p && p >= r) r = p+1; q = strrchr(b, ':'); if (q && q >= r) r = q+1; strcpy(r, "putty.hlp"); if ( (fp = fopen(b, "r")) != NULL) { help_path = dupstr(b); fclose(fp); } else help_path = NULL; } random_init(); return DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK; }
int main(int argc, char **argv) { int i, j; if (argc > 1) { /* * Generation of tests. * * Given `-splat <args>', we print out a C-style * representation of each argument (in the form "a", "b", * NULL), backslash-escaping each backslash and double * quote. * * Given `-split <string>', we first doctor `string' by * turning forward slashes into backslashes, single quotes * into double quotes and underscores into spaces; and then * we feed the resulting string to ourself with `-splat'. * * Given `-generate', we concoct a variety of fun test * cases, encode them in quote-safe form (mapping \, " and * space to /, ' and _ respectively) and feed each one to * `-split'. */ if (!strcmp(argv[1], "-splat")) { int i; char *p; for (i = 2; i < argc; i++) { putchar('"'); for (p = argv[i]; *p; p++) { if (*p == '\\' || *p == '"') putchar('\\'); putchar(*p); } printf("\", "); } printf("NULL"); return 0; } if (!strcmp(argv[1], "-split") && argc > 2) { char *str = malloc(20 + strlen(argv[0]) + strlen(argv[2])); char *p, *q; q = str + sprintf(str, "%s -splat ", argv[0]); printf(" {\""); for (p = argv[2]; *p; p++, q++) { switch (*p) { case '/': printf("\\\\"); *q = '\\'; break; case '\'': printf("\\\""); *q = '"'; break; case '_': printf(" "); *q = ' '; break; default: putchar(*p); *q = *p; break; } } *p = '\0'; printf("\", {"); fflush(stdout); system(str); printf("}},\n"); return 0; } if (!strcmp(argv[1], "-generate")) { char *teststr, *p; int i, initialquote, backslashes, quotes; teststr = malloc(200 + strlen(argv[0])); for (initialquote = 0; initialquote <= 1; initialquote++) { for (backslashes = 0; backslashes < 5; backslashes++) { for (quotes = 0; quotes < 9; quotes++) { p = teststr + sprintf(teststr, "%s -split ", argv[0]); if (initialquote) *p++ = '\''; *p++ = 'a'; for (i = 0; i < backslashes; i++) *p++ = '/'; for (i = 0; i < quotes; i++) *p++ = '\''; *p++ = 'b'; *p++ = '_'; *p++ = 'c'; *p++ = '\''; *p++ = '_'; *p++ = 'd'; *p = '\0'; system(teststr); } } } return 0; } fprintf(stderr, "unrecognised option: \"%s\"\n", argv[1]); return 1; } /* * If we get here, we were invoked with no arguments, so just * run the tests. */ for (i = 0; i < lenof(argv_tests); i++) { int ac; char **av; split_into_argv(argv_tests[i].cmdline, &ac, &av); for (j = 0; j < ac && argv_tests[i].argv[j]; j++) { if (strcmp(av[j], argv_tests[i].argv[j])) { printf("failed test %d (|%s|) arg %d: |%s| should be |%s|\n", i, argv_tests[i].cmdline, j, av[j], argv_tests[i].argv[j]); } #ifdef VERBOSE else { printf("test %d (|%s|) arg %d: |%s| == |%s|\n", i, argv_tests[i].cmdline, j, av[j], argv_tests[i].argv[j]); } #endif } if (j < ac) printf("failed test %d (|%s|): %d args returned, should be %d\n", i, argv_tests[i].cmdline, ac, j); if (argv_tests[i].argv[j]) printf("failed test %d (|%s|): %d args returned, should be more\n", i, argv_tests[i].cmdline, ac); } return 0; }
/* * 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); } }