cmdline_arg.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Implementation of the CmdlineArg abstraction for Unix
  3. */
  4. #include "putty.h"
  5. typedef struct CmdlineArgUnix CmdlineArgUnix;
  6. struct CmdlineArgUnix {
  7. /*
  8. * This is a writable char *, because the arguments received by
  9. * main() really are writable, and moreover, you _want_ to write
  10. * over them in some circumstances, to manipulate how your program
  11. * shows up in ps(1). Our example is wiping out the argument to
  12. * the -pw option. This isn't robust - you need to not use that
  13. * option at all if you want zero risk of password exposure
  14. * through ps - but we do the best we can.
  15. *
  16. * Some CmdlineArg structures are invented after the program
  17. * starts, in which case they don't correspond to real argv words
  18. * at all, and this pointer is NULL.
  19. */
  20. char *argv_word;
  21. /*
  22. * A CmdlineArg invented later might need to store a string that
  23. * will be freed when it goes away. This pointer is non-NULL if
  24. * freeing needs to happen.
  25. */
  26. char *to_free;
  27. /*
  28. * This const char * is the real string value of the argument.
  29. */
  30. const char *value;
  31. /*
  32. * Our index in the CmdlineArgList, or (size_t)-1 if we don't have
  33. * one and are an argument invented later.
  34. */
  35. size_t index;
  36. /*
  37. * Public part of the structure.
  38. */
  39. CmdlineArg argp;
  40. };
  41. static CmdlineArgUnix *cmdline_arg_new_in_list(CmdlineArgList *list)
  42. {
  43. CmdlineArgUnix *arg = snew(CmdlineArgUnix);
  44. arg->argv_word = NULL;
  45. arg->to_free = NULL;
  46. arg->value = NULL;
  47. arg->index = (size_t)-1;
  48. arg->argp.list = list;
  49. sgrowarray(list->args, list->argssize, list->nargs);
  50. list->args[list->nargs++] = &arg->argp;
  51. return arg;
  52. }
  53. static CmdlineArg *cmdline_arg_from_argv_word(CmdlineArgList *list, char *word)
  54. {
  55. CmdlineArgUnix *arg = cmdline_arg_new_in_list(list);
  56. arg->argv_word = word;
  57. arg->value = arg->argv_word;
  58. return &arg->argp;
  59. }
  60. CmdlineArgList *cmdline_arg_list_from_argv(int argc, char **argv)
  61. {
  62. CmdlineArgList *list = snew(CmdlineArgList);
  63. list->args = NULL;
  64. list->nargs = list->argssize = 0;
  65. for (int i = 1; i < argc; i++) {
  66. CmdlineArg *argp = cmdline_arg_from_argv_word(list, argv[i]);
  67. CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
  68. arg->index = i - 1; /* index in list->args[], not in argv[] */
  69. }
  70. sgrowarray(list->args, list->argssize, list->nargs);
  71. list->args[list->nargs++] = NULL;
  72. return list;
  73. }
  74. void cmdline_arg_free(CmdlineArg *argp)
  75. {
  76. if (!argp)
  77. return;
  78. CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
  79. if (arg->to_free)
  80. burnstr(arg->to_free);
  81. sfree(arg);
  82. }
  83. void cmdline_arg_list_free(CmdlineArgList *list)
  84. {
  85. for (size_t i = 0; i < list->nargs; i++)
  86. cmdline_arg_free(list->args[i]);
  87. sfree(list->args);
  88. sfree(list);
  89. }
  90. CmdlineArg *cmdline_arg_from_str(CmdlineArgList *list, const char *string)
  91. {
  92. CmdlineArgUnix *arg = cmdline_arg_new_in_list(list);
  93. arg->to_free = dupstr(string);
  94. arg->value = arg->to_free;
  95. return &arg->argp;
  96. }
  97. const char *cmdline_arg_to_str(CmdlineArg *argp)
  98. {
  99. if (!argp)
  100. return NULL;
  101. CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
  102. return arg->value;
  103. }
  104. const char *cmdline_arg_to_utf8(CmdlineArg *argp)
  105. {
  106. /* For the moment, return NULL. But perhaps it makes sense to
  107. * convert from the default locale into UTF-8? */
  108. return NULL;
  109. }
  110. Filename *cmdline_arg_to_filename(CmdlineArg *argp)
  111. {
  112. if (!argp)
  113. return NULL;
  114. CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
  115. return filename_from_str(arg->value);
  116. }
  117. void cmdline_arg_wipe(CmdlineArg *argp)
  118. {
  119. if (!argp)
  120. return;
  121. CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
  122. if (arg->argv_word)
  123. smemclr(arg->argv_word, strlen(arg->argv_word));
  124. }
  125. char **cmdline_arg_remainder(CmdlineArg *argp)
  126. {
  127. CmdlineArgUnix *arg = container_of(argp, CmdlineArgUnix, argp);
  128. CmdlineArgList *list = argp->list;
  129. size_t index = arg->index;
  130. assert(index != (size_t)-1);
  131. size_t nargs = 0;
  132. while (list->args[index + nargs])
  133. nargs++;
  134. char **argv = snewn(nargs + 1, char *);
  135. for (size_t i = 0; i < nargs; i++) {
  136. CmdlineArg *ith_argp = list->args[index + i];
  137. CmdlineArgUnix *ith_arg = container_of(ith_argp, CmdlineArgUnix, argp);
  138. argv[i] = ith_arg->argv_word;
  139. }
  140. argv[nargs] = NULL;
  141. return argv;
  142. }