mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
74150633f1
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().
168 lines
4.4 KiB
C
168 lines
4.4 KiB
C
/*
|
|
* Implementation of the CmdlineArg abstraction for Unix
|
|
*/
|
|
|
|
#include "putty.h"
|
|
|
|
typedef struct CmdlineArgUnix CmdlineArgUnix;
|
|
struct CmdlineArgUnix {
|
|
/*
|
|
* This is a writable char *, because the arguments received by
|
|
* main() really are writable, and moreover, you _want_ to write
|
|
* over them in some circumstances, to manipulate how your program
|
|
* shows up in ps(1). Our example is wiping out the argument to
|
|
* the -pw option. This isn't robust - you need to not use that
|
|
* option at all if you want zero risk of password exposure
|
|
* through ps - but we do the best we can.
|
|
*
|
|
* Some CmdlineArg structures are invented after the program
|
|
* starts, in which case they don't correspond to real argv words
|
|
* at all, and this pointer is NULL.
|
|
*/
|
|
char *argv_word;
|
|
|
|
/*
|
|
* A CmdlineArg invented later might need to store a string that
|
|
* will be freed when it goes away. This pointer is non-NULL if
|
|
* freeing needs to happen.
|
|
*/
|
|
char *to_free;
|
|
|
|
/*
|
|
* This const char * is the real string value of the argument.
|
|
*/
|
|
const char *value;
|
|
|
|
/*
|
|
* Our index in the CmdlineArgList, or (size_t)-1 if we don't have
|
|
* one and are an argument invented later.
|
|
*/
|
|
size_t index;
|
|
|
|
/*
|
|
* Public part of the structure.
|
|
*/
|
|
CmdlineArg argp;
|
|
};
|
|
|
|
static CmdlineArgUnix *cmdline_arg_new_in_list(CmdlineArgList *list)
|
|
{
|
|
CmdlineArgUnix *arg = snew(CmdlineArgUnix);
|
|
arg->argv_word = NULL;
|
|
arg->to_free = NULL;
|
|
arg->value = NULL;
|
|
arg->index = (size_t)-1;
|
|
arg->argp.list = list;
|
|
sgrowarray(list->args, list->argssize, list->nargs);
|
|
list->args[list->nargs++] = &arg->argp;
|
|
return arg;
|
|
}
|
|
|
|
static CmdlineArg *cmdline_arg_from_argv_word(CmdlineArgList *list, char *word)
|
|
{
|
|
CmdlineArgUnix *arg = cmdline_arg_new_in_list(list);
|
|
arg->argv_word = word;
|
|
arg->value = arg->argv_word;
|
|
return &arg->argp;
|
|
}
|
|
|
|
CmdlineArgList *cmdline_arg_list_from_argv(int argc, char **argv)
|
|
{
|
|
CmdlineArgList *list = snew(CmdlineArgList);
|
|
list->args = NULL;
|
|
list->nargs = list->argssize = 0;
|
|
for (int i = 1; i < argc; i++) {
|
|
CmdlineArg *argp = cmdline_arg_from_argv_word(list, argv[i]);
|
|
CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
|
|
arg->index = i - 1; /* index in list->args[], not in argv[] */
|
|
}
|
|
sgrowarray(list->args, list->argssize, list->nargs);
|
|
list->args[list->nargs++] = NULL;
|
|
return list;
|
|
}
|
|
|
|
void cmdline_arg_free(CmdlineArg *argp)
|
|
{
|
|
if (!argp)
|
|
return;
|
|
|
|
CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
|
|
if (arg->to_free)
|
|
burnstr(arg->to_free);
|
|
sfree(arg);
|
|
}
|
|
|
|
void cmdline_arg_list_free(CmdlineArgList *list)
|
|
{
|
|
for (size_t i = 0; i < list->nargs; i++)
|
|
cmdline_arg_free(list->args[i]);
|
|
sfree(list->args);
|
|
sfree(list);
|
|
}
|
|
|
|
CmdlineArg *cmdline_arg_from_str(CmdlineArgList *list, const char *string)
|
|
{
|
|
CmdlineArgUnix *arg = cmdline_arg_new_in_list(list);
|
|
arg->to_free = dupstr(string);
|
|
arg->value = arg->to_free;
|
|
return &arg->argp;
|
|
}
|
|
|
|
const char *cmdline_arg_to_str(CmdlineArg *argp)
|
|
{
|
|
if (!argp)
|
|
return NULL;
|
|
|
|
CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
|
|
return arg->value;
|
|
}
|
|
|
|
const char *cmdline_arg_to_utf8(CmdlineArg *argp)
|
|
{
|
|
/* For the moment, return NULL. But perhaps it makes sense to
|
|
* convert from the default locale into UTF-8? */
|
|
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)
|
|
{
|
|
if (!argp)
|
|
return;
|
|
|
|
CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
|
|
if (arg->argv_word)
|
|
smemclr(arg->argv_word, strlen(arg->argv_word));
|
|
}
|
|
|
|
char **cmdline_arg_remainder(CmdlineArg *argp)
|
|
{
|
|
CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
|
|
CmdlineArgList *list = argp->list;
|
|
|
|
size_t index = arg->index;
|
|
assert(index != (size_t)-1);
|
|
|
|
size_t nargs = 0;
|
|
while (list->args[index + nargs])
|
|
nargs++;
|
|
|
|
char **argv = snewn(nargs + 1, char *);
|
|
for (size_t i = 0; i < nargs; i++) {
|
|
CmdlineArg *ith_argp = list->args[index + i];
|
|
CmdlineArgUnix *ith_arg = container_of(ith_argp, CmdlineArgUnix, argp);
|
|
argv[i] = ith_arg->argv_word;
|
|
}
|
|
argv[nargs] = NULL;
|
|
|
|
return argv;
|
|
}
|