1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-03-31 02:32:49 -05:00

Add and use cmdline_arg_to_filename().

Converting a CmdlineArg straight to a Filename allows us to make the
filename out of the wide-character version of the string on Windows.
So now filenames specified on the command line should generally be
able to handle pathnames containing Unicode characters not in the
system code page.

This change also involves making some char pointers _into_ Filename
structs where they weren't previously: for example, the
'openssh_config_file' variable in Windows Pageant's WinMain().
This commit is contained in:
Simon Tatham 2024-09-24 17:50:19 +01:00
parent b57fb48b27
commit 74150633f1
12 changed files with 61 additions and 41 deletions

View File

@ -563,20 +563,23 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg,
sfree(host); sfree(host);
} }
if (!strcmp(p, "-m")) { if (!strcmp(p, "-m")) {
const char *filename; Filename *filename;
FILE *fp; FILE *fp;
RETURN(2); RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
SAVEABLE(0); SAVEABLE(0);
filename = value; filename = cmdline_arg_to_filename(nextarg);
fp = fopen(filename, "r"); fp = f_open(filename, "r", false);
if (!fp) { if (!fp) {
cmdline_error("unable to open command file \"%s\"", filename); cmdline_error("unable to open command file \"%s\"",
filename_to_str(filename));
filename_free(filename);
return ret; return ret;
} }
filename_free(filename);
strbuf *command = strbuf_new(); strbuf *command = strbuf_new();
char readbuf[4096]; char readbuf[4096];
while (1) { while (1) {
@ -628,7 +631,7 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg,
cmdline_error("the -pwfile option can only be used with the " cmdline_error("the -pwfile option can only be used with the "
"SSH protocol"); "SSH protocol");
else { else {
Filename *fn = filename_from_str(value); Filename *fn = cmdline_arg_to_filename(nextarg);
FILE *fp = f_open(fn, "r", false); FILE *fp = f_open(fn, "r", false);
if (!fp) { if (!fp) {
cmdline_error("unable to open password file '%s'", value); cmdline_error("unable to open password file '%s'", value);
@ -750,21 +753,19 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg,
} }
if (!strcmp(p, "-i")) { if (!strcmp(p, "-i")) {
Filename *fn;
RETURN(2); RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0); SAVEABLE(0);
fn = filename_from_str(value); Filename *fn = cmdline_arg_to_filename(nextarg);
conf_set_filename(conf, CONF_keyfile, fn); conf_set_filename(conf, CONF_keyfile, fn);
filename_free(fn); filename_free(fn);
} }
if (!strcmp(p, "-cert")) { if (!strcmp(p, "-cert")) {
Filename *fn;
RETURN(2); RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0); SAVEABLE(0);
fn = filename_from_str(value); Filename *fn = cmdline_arg_to_filename(nextarg);
conf_set_filename(conf, CONF_detached_cert, fn); conf_set_filename(conf, CONF_detached_cert, fn);
filename_free(fn); filename_free(fn);
} }
@ -868,12 +869,11 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg,
} }
if (!strcmp(p, "-sessionlog")) { if (!strcmp(p, "-sessionlog")) {
Filename *fn;
RETURN(2); RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER);
/* but available even in TOOLTYPE_NONNETWORK, cf pterm "-log" */ /* but available even in TOOLTYPE_NONNETWORK, cf pterm "-log" */
SAVEABLE(0); SAVEABLE(0);
fn = filename_from_str(value); Filename *fn = cmdline_arg_to_filename(nextarg);
conf_set_filename(conf, CONF_logfilename, fn); conf_set_filename(conf, CONF_logfilename, fn);
conf_set_int(conf, CONF_logtype, LGTYP_DEBUG); conf_set_int(conf, CONF_logtype, LGTYP_DEBUG);
filename_free(fn); filename_free(fn);
@ -881,11 +881,10 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg,
if (!strcmp(p, "-sshlog") || if (!strcmp(p, "-sshlog") ||
!strcmp(p, "-sshrawlog")) { !strcmp(p, "-sshrawlog")) {
Filename *fn;
RETURN(2); RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
SAVEABLE(0); SAVEABLE(0);
fn = filename_from_str(value); Filename *fn = cmdline_arg_to_filename(nextarg);
conf_set_filename(conf, CONF_logfilename, fn); conf_set_filename(conf, CONF_logfilename, fn);
conf_set_int(conf, CONF_logtype, conf_set_int(conf, CONF_logtype,
!strcmp(p, "-sshlog") ? LGTYP_PACKETS : !strcmp(p, "-sshlog") ? LGTYP_PACKETS :

View File

@ -2436,6 +2436,7 @@ struct CmdlineArg {
}; };
const char *cmdline_arg_to_utf8(CmdlineArg *arg); /* may fail */ const char *cmdline_arg_to_utf8(CmdlineArg *arg); /* may fail */
const char *cmdline_arg_to_str(CmdlineArg *arg); /* must not fail */ const char *cmdline_arg_to_str(CmdlineArg *arg); /* must not fail */
Filename *cmdline_arg_to_filename(CmdlineArg *arg); /* caller must free */
void cmdline_arg_wipe(CmdlineArg *arg); void cmdline_arg_wipe(CmdlineArg *arg);
CmdlineArg *cmdline_arg_from_str(CmdlineArgList *list, const char *string); CmdlineArg *cmdline_arg_from_str(CmdlineArgList *list, const char *string);
/* Platforms provide their own constructors for CmdlineArgList */ /* Platforms provide their own constructors for CmdlineArgList */

View File

@ -476,10 +476,9 @@ bool do_cmdline(int argc, char **argv, bool do_everything, Conf *conf)
conf_set_str(conf, CONF_wintitle, val); conf_set_str(conf, CONF_wintitle, val);
} else if (!strcmp(p, "-log")) { } else if (!strcmp(p, "-log")) {
Filename *fn;
EXPECTS_ARG; EXPECTS_ARG;
SECOND_PASS_ONLY; SECOND_PASS_ONLY;
fn = filename_from_str(val); Filename *fn = cmdline_arg_to_filename(nextarg);
conf_set_filename(conf, CONF_logfilename, fn); conf_set_filename(conf, CONF_logfilename, fn);
conf_set_int(conf, CONF_logtype, LGTYP_DEBUG); conf_set_int(conf, CONF_logtype, LGTYP_DEBUG);
filename_free(fn); filename_free(fn);

View File

@ -124,6 +124,15 @@ const char *cmdline_arg_to_utf8(CmdlineArg *argp)
return NULL; return NULL;
} }
Filename *cmdline_arg_to_filename(CmdlineArg *argp)
{
if (!argp)
return NULL;
CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
return filename_from_str(arg->value);
}
void cmdline_arg_wipe(CmdlineArg *argp) void cmdline_arg_wipe(CmdlineArg *argp)
{ {
if (!argp) if (!argp)

View File

@ -459,7 +459,7 @@ static HTREEITEM treeview_insert(struct treeview_faff *faff,
return newitem; return newitem;
} }
const char *dialog_box_demo_screenshot_filename = NULL; Filename *dialog_box_demo_screenshot_filename = NULL;
/* ctrltrees indices for the main dialog box */ /* ctrltrees indices for the main dialog box */
enum { enum {

View File

@ -1537,7 +1537,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
const char *command = NULL; const char *command = NULL;
const char *unixsocket = NULL; const char *unixsocket = NULL;
bool show_keylist_on_startup = false; bool show_keylist_on_startup = false;
const char *openssh_config_file = NULL; Filename *openssh_config_file = NULL;
typedef struct CommandLineKey { typedef struct CommandLineKey {
Filename *fn; Filename *fn;
@ -1612,7 +1612,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
*/ */
sgrowarray(clkeys, clkeysize, nclkeys); sgrowarray(clkeys, clkeysize, nclkeys);
CommandLineKey *clkey = &clkeys[nclkeys++]; CommandLineKey *clkey = &clkeys[nclkeys++];
clkey->fn = filename_from_str(cmdline_arg_to_str(valarg)); clkey->fn = cmdline_arg_to_filename(valarg);
clkey->add_encrypted = add_keys_encrypted; clkey->add_encrypted = add_keys_encrypted;
} else if (match_opt("-pgpfp")) { } else if (match_opt("-pgpfp")) {
pgp_fingerprints_msgbox(NULL); pgp_fingerprints_msgbox(NULL);
@ -1628,8 +1628,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
} else if (match_opt("-keylist")) { } else if (match_opt("-keylist")) {
show_keylist_on_startup = true; show_keylist_on_startup = true;
} else if (match_optval("-openssh-config", "-openssh_config")) { } else if (match_optval("-openssh-config", "-openssh_config")) {
openssh_config_file = cmdline_arg_to_str(valarg); openssh_config_file = cmdline_arg_to_filename(valarg);
} else if (match_optval("-unix")) { } else if (match_optval("-unix")) {
/* UNICODE: should this be a Unicode filename? Is there a
* Unicode version of connect() that lets you give a
* Unicode pathname when making an AF_UNIX socket? */
unixsocket = cmdline_arg_to_str(valarg); unixsocket = cmdline_arg_to_str(valarg);
} else if (match_opt("-c")) { } else if (match_opt("-c")) {
/* /*
@ -1735,10 +1738,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
* pointing at the named pipe, do so. * pointing at the named pipe, do so.
*/ */
if (openssh_config_file) { if (openssh_config_file) {
FILE *fp = fopen(openssh_config_file, "w"); FILE *fp = f_open(openssh_config_file, "w", true);
if (!fp) { if (!fp) {
char *err = dupprintf("Unable to write OpenSSH config " char *err = dupprintf(
"file to %s", openssh_config_file); "Unable to write OpenSSH config file to %s",
filename_to_str(openssh_config_file));
MessageBox(NULL, err, "Pageant Error", MessageBox(NULL, err, "Pageant Error",
MB_ICONERROR | MB_OK); MB_ICONERROR | MB_OK);
return 1; return 1;
@ -1960,7 +1964,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
* Leave this file around, but empty it, so that it doesn't * Leave this file around, but empty it, so that it doesn't
* refer to a pipe we aren't listening on any more. * refer to a pipe we aren't listening on any more.
*/ */
FILE *fp = fopen(openssh_config_file, "w"); FILE *fp = f_open(openssh_config_file, "w", true);
if (fp) if (fp)
fclose(fp); fclose(fp);
} }

View File

@ -859,7 +859,7 @@ bool aux_match_opt(AuxMatchOpt *amo, CmdlineArg **val,
const char *optname, ...); const char *optname, ...);
bool aux_match_done(AuxMatchOpt *amo); bool aux_match_done(AuxMatchOpt *amo);
char *save_screenshot(HWND hwnd, const char *outfile); char *save_screenshot(HWND hwnd, Filename *outfile);
void gui_terminal_ready(HWND hwnd, Seat *seat, Backend *backend); void gui_terminal_ready(HWND hwnd, Seat *seat, Backend *backend);
void setup_gui_timing(void); void setup_gui_timing(void);

View File

@ -2,9 +2,9 @@
#include "storage.h" #include "storage.h"
extern bool sesslist_demo_mode; extern bool sesslist_demo_mode;
extern const char *dialog_box_demo_screenshot_filename; extern Filename *dialog_box_demo_screenshot_filename;
static strbuf *demo_terminal_data = NULL; static strbuf *demo_terminal_data = NULL;
static const char *terminal_demo_screenshot_filename; static Filename *terminal_demo_screenshot_filename;
const unsigned cmdline_tooltype = const unsigned cmdline_tooltype =
TOOLTYPE_HOST_ARG | TOOLTYPE_HOST_ARG |
@ -99,7 +99,7 @@ void gui_term_process_cmdline(Conf *conf, char *cmdline)
} else { } else {
demo_config_box = true; demo_config_box = true;
dialog_box_demo_screenshot_filename = dialog_box_demo_screenshot_filename =
cmdline_arg_to_str(arglist->args[arglistpos++]); cmdline_arg_to_filename(arglist->args[arglistpos++]);
} }
} else if (!strcmp(p, "-demo-terminal")) { } else if (!strcmp(p, "-demo-terminal")) {
if (!arglist->args[arglistpos] || if (!arglist->args[arglistpos] ||
@ -109,7 +109,7 @@ void gui_term_process_cmdline(Conf *conf, char *cmdline)
const char *infile = const char *infile =
cmdline_arg_to_str(arglist->args[arglistpos++]); cmdline_arg_to_str(arglist->args[arglistpos++]);
terminal_demo_screenshot_filename = terminal_demo_screenshot_filename =
cmdline_arg_to_str(arglist->args[arglistpos++]); cmdline_arg_to_filename(arglist->args[arglistpos++]);
FILE *fp = fopen(infile, "rb"); FILE *fp = fopen(infile, "rb");
if (!fp) if (!fp)
cmdline_error("can't open input file '%s'", infile); cmdline_error("can't open input file '%s'", infile);

View File

@ -26,9 +26,9 @@
#define DEFAULT_ECCURVE_INDEX 0 #define DEFAULT_ECCURVE_INDEX 0
#define DEFAULT_EDCURVE_INDEX 0 #define DEFAULT_EDCURVE_INDEX 0
static const char *cmdline_keyfile = NULL; static Filename *cmdline_keyfile = NULL;
static ptrlen cmdline_demo_keystr; static ptrlen cmdline_demo_keystr;
static const char *demo_screenshot_filename = NULL; static Filename *demo_screenshot_filename = NULL;
/* /*
* Print a modal (Really Bad) message box and perform a fatal exit. * Print a modal (Really Bad) message box and perform a fatal exit.
@ -1737,9 +1737,7 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
* Load a key file if one was provided on the command line. * Load a key file if one was provided on the command line.
*/ */
if (cmdline_keyfile) { if (cmdline_keyfile) {
Filename *fn = filename_from_str(cmdline_keyfile); load_key_file(hwnd, state, cmdline_keyfile, false);
load_key_file(hwnd, state, fn, false);
filename_free(fn);
} else if (cmdline_demo_keystr.ptr) { } else if (cmdline_demo_keystr.ptr) {
BinarySource src[1]; BinarySource src[1];
BinarySource_BARE_INIT_PL(src, cmdline_demo_keystr); BinarySource_BARE_INIT_PL(src, cmdline_demo_keystr);
@ -2430,7 +2428,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
* Assume the first argument to be a private key file, and * Assume the first argument to be a private key file, and
* attempt to load it. * attempt to load it.
*/ */
cmdline_keyfile = cmdline_arg_to_str(valarg); cmdline_keyfile = cmdline_arg_to_filename(valarg);
continue; continue;
} else { } else {
opt_error("unexpected extra argument '%s'\n", opt_error("unexpected extra argument '%s'\n",
@ -2550,7 +2548,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
} }
sfree(val); sfree(val);
} else if (match_optval("-demo-screenshot")) { } else if (match_optval("-demo-screenshot")) {
demo_screenshot_filename = cmdline_arg_to_str(valarg); demo_screenshot_filename = cmdline_arg_to_filename(valarg);
cmdline_demo_keystr = PTRLEN_LITERAL( cmdline_demo_keystr = PTRLEN_LITERAL(
"PuTTY-User-Key-File-3: ssh-ed25519\n" "PuTTY-User-Key-File-3: ssh-ed25519\n"
"Encryption: none\n" "Encryption: none\n"

View File

@ -15,7 +15,7 @@ void out_of_memory(void) { fatal_error("out of memory"); }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const char *outfile = NULL; Filename *outfile = NULL;
AuxMatchOpt amo = aux_match_opt_init(fatal_error); AuxMatchOpt amo = aux_match_opt_init(fatal_error);
while (!aux_match_done(&amo)) { while (!aux_match_done(&amo)) {
@ -28,7 +28,7 @@ int main(int argc, char **argv)
if (aux_match_arg(&amo, &val)) { if (aux_match_arg(&amo, &val)) {
fatal_error("unexpected argument '%s'", cmdline_arg_to_str(val)); fatal_error("unexpected argument '%s'", cmdline_arg_to_str(val));
} else if (match_optval("-o", "--output")) { } else if (match_optval("-o", "--output")) {
outfile = cmdline_arg_to_str(val); outfile = cmdline_arg_to_filename(val);
} else { } else {
fatal_error("unrecognised option '%s'\n", fatal_error("unrecognised option '%s'\n",
cmdline_arg_to_str(amo.arglist->args[amo.index])); cmdline_arg_to_str(amo.arglist->args[amo.index]));
@ -41,6 +41,7 @@ int main(int argc, char **argv)
char *err = save_screenshot(NULL, outfile); char *err = save_screenshot(NULL, outfile);
if (err) if (err)
fatal_error("%s", err); fatal_error("%s", err);
filename_free(outfile);
return 0; return 0;
} }

View File

@ -162,6 +162,15 @@ const char *cmdline_arg_to_utf8(CmdlineArg *argp)
return arg->utf8; return arg->utf8;
} }
Filename *cmdline_arg_to_filename(CmdlineArg *argp)
{
if (!argp)
return NULL;
CmdlineArgWin *arg = container_of(argp, CmdlineArgWin, argp);
return filename_from_wstr(arg->wide);
}
void cmdline_arg_wipe(CmdlineArg *argp) void cmdline_arg_wipe(CmdlineArg *argp)
{ {
if (!argp) if (!argp)

View File

@ -4,7 +4,7 @@
#include <dwmapi.h> #include <dwmapi.h>
char *save_screenshot(HWND hwnd, const char *outfile) char *save_screenshot(HWND hwnd, Filename *outfile)
{ {
HDC dcWindow = NULL, dcSave = NULL; HDC dcWindow = NULL, dcSave = NULL;
HBITMAP bmSave = NULL; HBITMAP bmSave = NULL;
@ -89,9 +89,9 @@ char *save_screenshot(HWND hwnd, const char *outfile)
err = dupprintf("GetDIBits (get data): %s", err = dupprintf("GetDIBits (get data): %s",
win_strerror(GetLastError())); win_strerror(GetLastError()));
FILE *fp = fopen(outfile, "wb"); FILE *fp = f_open(outfile, "wb", false);
if (!fp) { if (!fp) {
err = dupprintf("'%s': unable to open file", outfile); err = dupprintf("'%s': unable to open file", filename_to_str(outfile));
goto out; goto out;
} }
@ -118,7 +118,7 @@ char *save_screenshot(HWND hwnd, const char *outfile)
#else /* HAVE_DWMAPI_H */ #else /* HAVE_DWMAPI_H */
/* Without <dwmapi.h> we can't get the right window rectangle */ /* Without <dwmapi.h> we can't get the right window rectangle */
char *save_screenshot(HWND hwnd, const char *outfile) char *save_screenshot(HWND hwnd, Filename *outfile)
{ {
return dupstr("Demo screenshots not compiled in to this build"); return dupstr("Demo screenshots not compiled in to this build");
} }