getopt_helpers.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2006, 2011, 2020 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file src/util/getopt_helpers.c
  18. * @brief implements command line that sets option
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #define LOG(kind, ...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__)
  24. /**
  25. * Print out program version (implements --version).
  26. *
  27. * @param ctx command line processing context
  28. * @param scls additional closure (points to version string)
  29. * @param option name of the option
  30. * @param value not used (NULL)
  31. * @return #GNUNET_NO (do not continue, not an error)
  32. */
  33. static int
  34. print_version (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  35. void *scls,
  36. const char *option,
  37. const char *value)
  38. {
  39. const char *version = scls;
  40. (void) option;
  41. (void) value;
  42. printf ("%s v%s\n", ctx->binaryName, version);
  43. return GNUNET_NO;
  44. }
  45. /**
  46. * Define the option to print the version of
  47. * the application (-v option)
  48. *
  49. * @param version string with the version number
  50. */
  51. struct GNUNET_GETOPT_CommandLineOption
  52. GNUNET_GETOPT_option_version (const char *version)
  53. {
  54. struct GNUNET_GETOPT_CommandLineOption clo = {
  55. .shortName = 'v',
  56. .name = "version",
  57. .description = gettext_noop (
  58. "print the version number"),
  59. .option_exclusive = 1,
  60. .processor = &print_version,
  61. .scls = (void *) version
  62. };
  63. return clo;
  64. }
  65. /**
  66. * At what offset does the help text start?
  67. */
  68. #define BORDER 29
  69. /**
  70. * Print out details on command line options (implements --help).
  71. *
  72. * @param ctx command line processing context
  73. * @param scls additional closure (points to about text)
  74. * @param option name of the option
  75. * @param value not used (NULL)
  76. * @return #GNUNET_NO (do not continue, not an error)
  77. */
  78. static int
  79. format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  80. void *scls,
  81. const char *option,
  82. const char *value)
  83. {
  84. const char *about = scls;
  85. size_t slen;
  86. unsigned int i;
  87. int j;
  88. size_t ml;
  89. size_t p;
  90. char *scp;
  91. const char *trans;
  92. const struct GNUNET_GETOPT_CommandLineOption *opt;
  93. const struct GNUNET_OS_ProjectData *pd;
  94. (void) option;
  95. (void) value;
  96. if (NULL != about)
  97. {
  98. printf ("%s\n%s\n", ctx->binaryOptions, gettext (about));
  99. printf (_ (
  100. "Arguments mandatory for long options are also mandatory for short options.\n"));
  101. }
  102. i = 0;
  103. opt = ctx->allOptions;
  104. while (NULL != opt[i].description)
  105. {
  106. if (opt[i].shortName == '\0')
  107. printf (" ");
  108. else
  109. printf (" -%c, ", opt[i].shortName);
  110. printf ("--%s", opt[i].name);
  111. slen = 8 + strlen (opt[i].name);
  112. if (NULL != opt[i].argumentHelp)
  113. {
  114. printf ("=%s", opt[i].argumentHelp);
  115. slen += 1 + strlen (opt[i].argumentHelp);
  116. }
  117. if (slen > BORDER)
  118. {
  119. printf ("\n%*s", BORDER, "");
  120. slen = BORDER;
  121. }
  122. if (slen < BORDER)
  123. {
  124. printf ("%*s", (int) (BORDER - slen), "");
  125. slen = BORDER;
  126. }
  127. if (0 < strlen (opt[i].description))
  128. trans = gettext (opt[i].description);
  129. else
  130. trans = "";
  131. ml = strlen (trans);
  132. p = 0;
  133. OUTER:
  134. while (ml - p > 78 - slen)
  135. {
  136. for (j = p + 78 - slen; j > (int) p; j--)
  137. {
  138. if (isspace ((unsigned char) trans[j]))
  139. {
  140. scp = GNUNET_malloc (j - p + 1);
  141. GNUNET_memcpy (scp, &trans[p], j - p);
  142. scp[j - p] = '\0';
  143. printf ("%s\n%*s", scp, BORDER + 2, "");
  144. GNUNET_free (scp);
  145. p = j + 1;
  146. slen = BORDER + 2;
  147. goto OUTER;
  148. }
  149. }
  150. /* could not find space to break line */
  151. scp = GNUNET_malloc (78 - slen + 1);
  152. GNUNET_memcpy (scp, &trans[p], 78 - slen);
  153. scp[78 - slen] = '\0';
  154. printf ("%s\n%*s", scp, BORDER + 2, "");
  155. GNUNET_free (scp);
  156. slen = BORDER + 2;
  157. p = p + 78 - slen;
  158. }
  159. /* print rest */
  160. if (p < ml)
  161. printf ("%s\n", &trans[p]);
  162. if (strlen (trans) == 0)
  163. printf ("\n");
  164. i++;
  165. }
  166. pd = GNUNET_OS_project_data_get ();
  167. printf ("Report bugs to %s.\n"
  168. "Home page: %s\n",
  169. pd->bug_email,
  170. pd->homepage);
  171. if (0 != pd->is_gnu)
  172. printf ("General help using GNU software: http://www.gnu.org/gethelp/\n");
  173. return GNUNET_NO;
  174. }
  175. /**
  176. * Defining the option to print the command line
  177. * help text (-h option).
  178. *
  179. * @param about string with brief description of the application
  180. */
  181. struct GNUNET_GETOPT_CommandLineOption
  182. GNUNET_GETOPT_option_help (const char *about)
  183. {
  184. struct GNUNET_GETOPT_CommandLineOption clo = {
  185. .shortName = 'h',
  186. .name = "help",
  187. .description = gettext_noop (
  188. "print this help"),
  189. .option_exclusive = 1,
  190. .processor = format_help,
  191. .scls = (void *) about
  192. };
  193. return clo;
  194. }
  195. /**
  196. * Set an option of type 'unsigned int' from the command line. Each
  197. * time the option flag is given, the value is incremented by one.
  198. * A pointer to this function should be passed as part of the
  199. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  200. * of this type. It should be followed by a pointer to a value of
  201. * type 'int'.
  202. *
  203. * @param ctx command line processing context
  204. * @param scls additional closure (will point to the 'unsigned int')
  205. * @param option name of the option
  206. * @param value not used (NULL)
  207. * @return #GNUNET_OK
  208. */
  209. static int
  210. increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  211. void *scls,
  212. const char *option,
  213. const char *value)
  214. {
  215. unsigned int *val = scls;
  216. (void) ctx;
  217. (void) option;
  218. (void) value;
  219. (*val)++;
  220. return GNUNET_OK;
  221. }
  222. /**
  223. * Increment @a val each time the option flag is given by one.
  224. *
  225. * @param shortName short name of the option
  226. * @param name long name of the option
  227. * @param argumentHelp help text for the option argument
  228. * @param description long help text for the option
  229. * @param[out] val increment by 1 each time the option is present
  230. */
  231. struct GNUNET_GETOPT_CommandLineOption
  232. GNUNET_GETOPT_option_increment_uint (char shortName,
  233. const char *name,
  234. const char *description,
  235. unsigned int *val)
  236. {
  237. struct GNUNET_GETOPT_CommandLineOption clo = {
  238. .shortName = shortName,
  239. .name = name,
  240. .description = description,
  241. .processor = &increment_value,
  242. .scls = (void *) val
  243. };
  244. return clo;
  245. }
  246. /**
  247. * Define the '-V' verbosity option. Using the option more
  248. * than once increments @a level each time.
  249. *
  250. * @param[out] level set to the verbosity level
  251. */
  252. struct GNUNET_GETOPT_CommandLineOption
  253. GNUNET_GETOPT_option_verbose (unsigned int *level)
  254. {
  255. struct GNUNET_GETOPT_CommandLineOption clo = {
  256. .shortName = 'V',
  257. .name = "verbose",
  258. .description =
  259. gettext_noop ("be verbose"),
  260. .processor = &increment_value,
  261. .scls = (void *) level
  262. };
  263. return clo;
  264. }
  265. /**
  266. * Set an option of type 'int' from the command line to 1 if the
  267. * given option is present.
  268. * A pointer to this function should be passed as part of the
  269. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  270. * of this type. It should be followed by a pointer to a value of
  271. * type 'int'.
  272. *
  273. * @param ctx command line processing context
  274. * @param scls additional closure (will point to the 'int')
  275. * @param option name of the option
  276. * @param value not used (NULL)
  277. * @return #GNUNET_OK
  278. */
  279. static int
  280. set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  281. void *scls,
  282. const char *option,
  283. const char *value)
  284. {
  285. int *val = scls;
  286. (void) ctx;
  287. (void) option;
  288. (void) value;
  289. *val = 1;
  290. return GNUNET_OK;
  291. }
  292. /**
  293. * Allow user to specify a flag (which internally means setting
  294. * an integer to 1/#GNUNET_YES/#GNUNET_OK.
  295. *
  296. * @param shortName short name of the option
  297. * @param name long name of the option
  298. * @param argumentHelp help text for the option argument
  299. * @param description long help text for the option
  300. * @param[out] val set to 1 if the option is present
  301. */
  302. struct GNUNET_GETOPT_CommandLineOption
  303. GNUNET_GETOPT_option_flag (char shortName,
  304. const char *name,
  305. const char *description,
  306. int *val)
  307. {
  308. struct GNUNET_GETOPT_CommandLineOption clo = {
  309. .shortName = shortName,
  310. .name = name,
  311. .description = description,
  312. .processor = &set_one,
  313. .scls = (void *) val
  314. };
  315. return clo;
  316. }
  317. /**
  318. * Set an option of type 'char *' from the command line.
  319. * A pointer to this function should be passed as part of the
  320. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  321. * of this type. It should be followed by a pointer to a value of
  322. * type 'char *', which will be allocated with the requested string.
  323. *
  324. * @param ctx command line processing context
  325. * @param scls additional closure (will point to the 'char *',
  326. * which will be allocated)
  327. * @param option name of the option
  328. * @param value actual value of the option (a string)
  329. * @return #GNUNET_OK
  330. */
  331. static int
  332. set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  333. void *scls,
  334. const char *option,
  335. const char *value)
  336. {
  337. char **val = scls;
  338. (void) ctx;
  339. (void) option;
  340. GNUNET_assert (NULL != value);
  341. GNUNET_free (*val);
  342. *val = GNUNET_strdup (value);
  343. return GNUNET_OK;
  344. }
  345. /**
  346. * Allow user to specify a string.
  347. *
  348. * @param shortName short name of the option
  349. * @param name long name of the option
  350. * @param argumentHelp help text for the option argument
  351. * @param description long help text for the option
  352. * @param[out] str set to the string
  353. */
  354. struct GNUNET_GETOPT_CommandLineOption
  355. GNUNET_GETOPT_option_string (char shortName,
  356. const char *name,
  357. const char *argumentHelp,
  358. const char *description,
  359. char **str)
  360. {
  361. struct GNUNET_GETOPT_CommandLineOption clo = {
  362. .shortName = shortName,
  363. .name = name,
  364. .argumentHelp = argumentHelp,
  365. .description = description,
  366. .require_argument = 1,
  367. .processor = &set_string,
  368. .scls = (void *) str
  369. };
  370. return clo;
  371. }
  372. /**
  373. * Define the '-L' log level option. Note that we do not check
  374. * that the log level is valid here.
  375. *
  376. * @param[out] level set to the log level
  377. */
  378. struct GNUNET_GETOPT_CommandLineOption
  379. GNUNET_GETOPT_option_loglevel (char **level)
  380. {
  381. struct GNUNET_GETOPT_CommandLineOption clo = {
  382. .shortName = 'L',
  383. .name = "log",
  384. .argumentHelp = "LOGLEVEL",
  385. .description = gettext_noop ("configure logging to use LOGLEVEL"),
  386. .require_argument = 1,
  387. .processor = &set_string,
  388. .scls = (void *) level
  389. };
  390. return clo;
  391. }
  392. /**
  393. * Set an option of type 'char *' from the command line with
  394. * filename expansion a la #GNUNET_STRINGS_filename_expand().
  395. *
  396. * @param ctx command line processing context
  397. * @param scls additional closure (will point to the `char *`,
  398. * which will be allocated)
  399. * @param option name of the option
  400. * @param value actual value of the option (a string)
  401. * @return #GNUNET_OK
  402. */
  403. static int
  404. set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  405. void *scls,
  406. const char *option,
  407. const char *value)
  408. {
  409. char **val = scls;
  410. (void) ctx;
  411. (void) option;
  412. GNUNET_assert (NULL != value);
  413. GNUNET_free (*val);
  414. *val = GNUNET_STRINGS_filename_expand (value);
  415. return GNUNET_OK;
  416. }
  417. /**
  418. * Allow user to specify a filename (automatically path expanded).
  419. *
  420. * @param shortName short name of the option
  421. * @param name long name of the option
  422. * @param argumentHelp help text for the option argument
  423. * @param description long help text for the option
  424. * @param[out] str set to the string
  425. */
  426. struct GNUNET_GETOPT_CommandLineOption
  427. GNUNET_GETOPT_option_filename (char shortName,
  428. const char *name,
  429. const char *argumentHelp,
  430. const char *description,
  431. char **str)
  432. {
  433. struct GNUNET_GETOPT_CommandLineOption clo = {
  434. .shortName = shortName,
  435. .name = name,
  436. .argumentHelp = argumentHelp,
  437. .description = description,
  438. .require_argument = 1,
  439. .processor = &set_filename,
  440. .scls = (void *) str
  441. };
  442. return clo;
  443. }
  444. /**
  445. * Allow user to specify log file name (-l option)
  446. *
  447. * @param[out] logfn set to the name of the logfile
  448. */
  449. struct GNUNET_GETOPT_CommandLineOption
  450. GNUNET_GETOPT_option_logfile (char **logfn)
  451. {
  452. struct GNUNET_GETOPT_CommandLineOption clo = {
  453. .shortName = 'l',
  454. .name = "logfile",
  455. .argumentHelp = "FILENAME",
  456. .description =
  457. gettext_noop ("configure logging to write logs to FILENAME"),
  458. .require_argument = 1,
  459. .processor = &set_filename,
  460. .scls = (void *) logfn
  461. };
  462. return clo;
  463. }
  464. /**
  465. * Allow user to specify configuration file name (-c option)
  466. *
  467. * @param[out] fn set to the name of the configuration file
  468. */
  469. struct GNUNET_GETOPT_CommandLineOption
  470. GNUNET_GETOPT_option_cfgfile (char **fn)
  471. {
  472. struct GNUNET_GETOPT_CommandLineOption clo = {
  473. .shortName = 'c',
  474. .name = "config",
  475. .argumentHelp = "FILENAME",
  476. .description = gettext_noop ("use configuration file FILENAME"),
  477. .require_argument = 1,
  478. .processor = &set_filename,
  479. .scls = (void *) fn
  480. };
  481. return clo;
  482. }
  483. /**
  484. * Set an option of type 'unsigned long long' from the command line.
  485. * A pointer to this function should be passed as part of the
  486. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  487. * of this type. It should be followed by a pointer to a value of
  488. * type 'unsigned long long'.
  489. *
  490. * @param ctx command line processing context
  491. * @param scls additional closure (will point to the 'unsigned long long')
  492. * @param option name of the option
  493. * @param value actual value of the option as a string.
  494. * @return #GNUNET_OK if parsing the value worked
  495. */
  496. static int
  497. set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  498. void *scls,
  499. const char *option,
  500. const char *value)
  501. {
  502. unsigned long long *val = scls;
  503. char dummy[2];
  504. (void) ctx;
  505. if (1 != sscanf (value, "%llu%1s", val, dummy))
  506. {
  507. fprintf (stderr,
  508. _ ("You must pass a number to the `%s' option.\n"),
  509. option);
  510. return GNUNET_SYSERR;
  511. }
  512. return GNUNET_OK;
  513. }
  514. /**
  515. * Allow user to specify an `unsigned long long`
  516. *
  517. * @param shortName short name of the option
  518. * @param name long name of the option
  519. * @param argumentHelp help text for the option argument
  520. * @param description long help text for the option
  521. * @param[out] val set to the value specified at the command line
  522. */
  523. struct GNUNET_GETOPT_CommandLineOption
  524. GNUNET_GETOPT_option_ulong (char shortName,
  525. const char *name,
  526. const char *argumentHelp,
  527. const char *description,
  528. unsigned long long *val)
  529. {
  530. struct GNUNET_GETOPT_CommandLineOption clo = {
  531. .shortName = shortName,
  532. .name = name,
  533. .argumentHelp = argumentHelp,
  534. .description = description,
  535. .require_argument = 1,
  536. .processor = &set_ulong,
  537. .scls = (void *) val
  538. };
  539. return clo;
  540. }
  541. /**
  542. * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
  543. * A pointer to this function should be passed as part of the
  544. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  545. * of this type. It should be followed by a pointer to a value of
  546. * type 'struct GNUNET_TIME_Relative'.
  547. *
  548. * @param ctx command line processing context
  549. * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
  550. * @param option name of the option
  551. * @param value actual value of the option as a string.
  552. * @return #GNUNET_OK if parsing the value worked
  553. */
  554. static int
  555. set_timetravel_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  556. void *scls,
  557. const char *option,
  558. const char *value)
  559. {
  560. long long delta;
  561. long long minus;
  562. struct GNUNET_TIME_Relative rt;
  563. (void) scls;
  564. (void) ctx;
  565. while (isspace (value[0]))
  566. value++;
  567. minus = 1;
  568. if (value[0] == '-')
  569. {
  570. minus = -1;
  571. value++;
  572. }
  573. else if (value[0] == '+')
  574. {
  575. value++;
  576. }
  577. if (GNUNET_OK !=
  578. GNUNET_STRINGS_fancy_time_to_relative (value,
  579. &rt))
  580. {
  581. fprintf (stderr,
  582. _ (
  583. "You must pass a relative time (optionally with sign) to the `%s' option.\n"),
  584. option);
  585. return GNUNET_SYSERR;
  586. }
  587. if (rt.rel_value_us > LLONG_MAX)
  588. {
  589. fprintf (stderr,
  590. _ ("Value given for time travel `%s' option is too big.\n"),
  591. option);
  592. return GNUNET_SYSERR;
  593. }
  594. delta = (long long) rt.rel_value_us;
  595. delta *= minus;
  596. GNUNET_TIME_set_offset (delta);
  597. return GNUNET_OK;
  598. }
  599. /**
  600. * Allow user to specify a `long long` with an offset to add to the current
  601. * system time to construct the time seen by the application. Used for
  602. * debugging / testing.
  603. *
  604. * @param shortName short name of the option
  605. * @param name long name of the option
  606. * @param[out] val set to the time specified at the command line
  607. */
  608. struct GNUNET_GETOPT_CommandLineOption
  609. GNUNET_GETOPT_option_timetravel (char shortName,
  610. const char *name)
  611. {
  612. struct GNUNET_GETOPT_CommandLineOption clo = {
  613. .shortName = shortName,
  614. .name = name,
  615. .argumentHelp = _ ("[+/-]MICROSECONDS"),
  616. .description = _ (
  617. "modify system time by given offset (for debugging/testing only)"),
  618. .require_argument = 1,
  619. .processor =
  620. &set_timetravel_time
  621. };
  622. return clo;
  623. }
  624. /**
  625. * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
  626. * A pointer to this function should be passed as part of the
  627. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  628. * of this type. It should be followed by a pointer to a value of
  629. * type 'struct GNUNET_TIME_Relative'.
  630. *
  631. * @param ctx command line processing context
  632. * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
  633. * @param option name of the option
  634. * @param value actual value of the option as a string.
  635. * @return #GNUNET_OK if parsing the value worked
  636. */
  637. static int
  638. set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  639. void *scls,
  640. const char *option,
  641. const char *value)
  642. {
  643. struct GNUNET_TIME_Relative *val = scls;
  644. (void) ctx;
  645. if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (value, val))
  646. {
  647. fprintf (stderr,
  648. _ ("You must pass relative time to the `%s' option.\n"),
  649. option);
  650. return GNUNET_SYSERR;
  651. }
  652. return GNUNET_OK;
  653. }
  654. /**
  655. * Allow user to specify a `struct GNUNET_TIME_Relative`
  656. * (using human-readable "fancy" time).
  657. *
  658. * @param shortName short name of the option
  659. * @param name long name of the option
  660. * @param argumentHelp help text for the option argument
  661. * @param description long help text for the option
  662. * @param[out] val set to the time specified at the command line
  663. */
  664. struct GNUNET_GETOPT_CommandLineOption
  665. GNUNET_GETOPT_option_relative_time (char shortName,
  666. const char *name,
  667. const char *argumentHelp,
  668. const char *description,
  669. struct GNUNET_TIME_Relative *val)
  670. {
  671. struct GNUNET_GETOPT_CommandLineOption clo = {
  672. .shortName = shortName,
  673. .name = name,
  674. .argumentHelp = argumentHelp,
  675. .description = description,
  676. .require_argument = 1,
  677. .processor =
  678. &set_relative_time,
  679. .scls = (void *) val
  680. };
  681. return clo;
  682. }
  683. /**
  684. * Set an option of type 'struct GNUNET_TIME_Absolute' from the command line.
  685. * A pointer to this function should be passed as part of the
  686. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  687. * of this type. It should be followed by a pointer to a value of
  688. * type 'struct GNUNET_TIME_Absolute'.
  689. *
  690. * @param ctx command line processing context
  691. * @param scls additional closure (will point to the `struct GNUNET_TIME_Absolute`)
  692. * @param option name of the option
  693. * @param value actual value of the option as a string.
  694. * @return #GNUNET_OK if parsing the value worked
  695. */
  696. static int
  697. set_absolute_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  698. void *scls,
  699. const char *option,
  700. const char *value)
  701. {
  702. struct GNUNET_TIME_Absolute *val = scls;
  703. (void) ctx;
  704. if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (value, val))
  705. {
  706. fprintf (stderr,
  707. _ ("You must pass absolute time to the `%s' option.\n"),
  708. option);
  709. return GNUNET_SYSERR;
  710. }
  711. return GNUNET_OK;
  712. }
  713. /**
  714. * Allow user to specify a `struct GNUNET_TIME_Absolute`
  715. * (using human-readable "fancy" time).
  716. *
  717. * @param shortName short name of the option
  718. * @param name long name of the option
  719. * @param argumentHelp help text for the option argument
  720. * @param description long help text for the option
  721. * @param[out] val set to the time specified at the command line
  722. */
  723. struct GNUNET_GETOPT_CommandLineOption
  724. GNUNET_GETOPT_option_absolute_time (char shortName,
  725. const char *name,
  726. const char *argumentHelp,
  727. const char *description,
  728. struct GNUNET_TIME_Absolute *val)
  729. {
  730. struct GNUNET_GETOPT_CommandLineOption clo = {
  731. .shortName = shortName,
  732. .name = name,
  733. .argumentHelp = argumentHelp,
  734. .description = description,
  735. .require_argument = 1,
  736. .processor =
  737. &set_absolute_time,
  738. .scls = (void *) val
  739. };
  740. return clo;
  741. }
  742. /**
  743. * Set an option of type 'unsigned int' from the command line.
  744. * A pointer to this function should be passed as part of the
  745. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  746. * of this type. It should be followed by a pointer to a value of
  747. * type 'unsigned int'.
  748. *
  749. * @param ctx command line processing context
  750. * @param scls additional closure (will point to the 'unsigned int')
  751. * @param option name of the option
  752. * @param value actual value of the option as a string.
  753. * @return #GNUNET_OK if parsing the value worked
  754. */
  755. static int
  756. set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  757. void *scls,
  758. const char *option,
  759. const char *value)
  760. {
  761. unsigned int *val = scls;
  762. char dummy[2];
  763. (void) ctx;
  764. if ('-' == *value)
  765. {
  766. fprintf (stderr,
  767. _ (
  768. "Your input for the '%s' option has to be a non negative number\n"),
  769. option);
  770. return GNUNET_SYSERR;
  771. }
  772. if (1 != sscanf (value, "%u%1s", val, dummy))
  773. {
  774. fprintf (stderr,
  775. _ ("You must pass a number to the `%s' option.\n"),
  776. option);
  777. return GNUNET_SYSERR;
  778. }
  779. return GNUNET_OK;
  780. }
  781. /**
  782. * Allow user to specify an unsigned integer.
  783. *
  784. * @param shortName short name of the option
  785. * @param name long name of the option
  786. * @param argumentHelp help text for the option argument
  787. * @param description long help text for the option
  788. * @param[out] val set to the value specified at the command line
  789. */
  790. struct GNUNET_GETOPT_CommandLineOption
  791. GNUNET_GETOPT_option_uint (char shortName,
  792. const char *name,
  793. const char *argumentHelp,
  794. const char *description,
  795. unsigned int *val)
  796. {
  797. struct GNUNET_GETOPT_CommandLineOption clo = {
  798. .shortName = shortName,
  799. .name = name,
  800. .argumentHelp = argumentHelp,
  801. .description = description,
  802. .require_argument = 1,
  803. .processor = &set_uint,
  804. .scls = (void *) val
  805. };
  806. return clo;
  807. }
  808. /**
  809. * Set an option of type 'uint16_t' from the command line.
  810. * A pointer to this function should be passed as part of the
  811. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  812. * of this type. It should be followed by a pointer to a value of
  813. * type 'uint16_t'.
  814. *
  815. * @param ctx command line processing context
  816. * @param scls additional closure (will point to the 'unsigned int')
  817. * @param option name of the option
  818. * @param value actual value of the option as a string.
  819. * @return #GNUNET_OK if parsing the value worked
  820. */
  821. static int
  822. set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  823. void *scls,
  824. const char *option,
  825. const char *value)
  826. {
  827. uint16_t *val = scls;
  828. unsigned int v;
  829. char dummy[2];
  830. (void) ctx;
  831. if (1 != sscanf (value, "%u%1s", &v, dummy))
  832. {
  833. fprintf (stderr,
  834. _ ("You must pass a number to the `%s' option.\n"),
  835. option);
  836. return GNUNET_SYSERR;
  837. }
  838. if (v > UINT16_MAX)
  839. {
  840. fprintf (stderr,
  841. _ ("You must pass a number below %u to the `%s' option.\n"),
  842. (unsigned int) UINT16_MAX,
  843. option);
  844. return GNUNET_SYSERR;
  845. }
  846. *val = (uint16_t) v;
  847. return GNUNET_OK;
  848. }
  849. /**
  850. * Allow user to specify an uint16_t.
  851. *
  852. * @param shortName short name of the option
  853. * @param name long name of the option
  854. * @param argumentHelp help text for the option argument
  855. * @param description long help text for the option
  856. * @param[out] val set to the value specified at the command line
  857. */
  858. struct GNUNET_GETOPT_CommandLineOption
  859. GNUNET_GETOPT_option_uint16 (char shortName,
  860. const char *name,
  861. const char *argumentHelp,
  862. const char *description,
  863. uint16_t *val)
  864. {
  865. struct GNUNET_GETOPT_CommandLineOption clo = {
  866. .shortName = shortName,
  867. .name = name,
  868. .argumentHelp = argumentHelp,
  869. .description = description,
  870. .require_argument = 1,
  871. .processor = &set_uint16,
  872. .scls = (void *) val
  873. };
  874. return clo;
  875. }
  876. /**
  877. * Closure for #set_base32().
  878. */
  879. struct Base32Context
  880. {
  881. /**
  882. * Value to initialize (already allocated)
  883. */
  884. void *val;
  885. /**
  886. * Number of bytes expected for @e val.
  887. */
  888. size_t val_size;
  889. };
  890. /**
  891. * Set an option of type 'unsigned int' from the command line.
  892. * A pointer to this function should be passed as part of the
  893. * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
  894. * of this type. It should be followed by a pointer to a value of
  895. * type 'unsigned int'.
  896. *
  897. * @param ctx command line processing context
  898. * @param scls additional closure (will point to the 'unsigned int')
  899. * @param option name of the option
  900. * @param value actual value of the option as a string.
  901. * @return #GNUNET_OK if parsing the value worked
  902. */
  903. static int
  904. set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
  905. void *scls,
  906. const char *option,
  907. const char *value)
  908. {
  909. struct Base32Context *bc = scls;
  910. (void) ctx;
  911. if (GNUNET_OK != GNUNET_STRINGS_string_to_data (value,
  912. strlen (value),
  913. bc->val,
  914. bc->val_size))
  915. {
  916. fprintf (
  917. stderr,
  918. _ (
  919. "Argument `%s' malformed. Expected base32 (Crockford) encoded value.\n"),
  920. option);
  921. return GNUNET_SYSERR;
  922. }
  923. return GNUNET_OK;
  924. }
  925. /**
  926. * Helper function to clean up after
  927. * #GNUNET_GETOPT_option_base32_fixed_size.
  928. *
  929. * @param cls value to GNUNET_free()
  930. */
  931. static void
  932. free_bc (void *cls)
  933. {
  934. GNUNET_free (cls);
  935. }
  936. /**
  937. * Allow user to specify a binary value using Crockford
  938. * Base32 encoding.
  939. *
  940. * @param shortName short name of the option
  941. * @param name long name of the option
  942. * @param argumentHelp help text for the option argument
  943. * @param description long help text for the option
  944. * @param[out] val binary value decoded from Crockford Base32-encoded argument
  945. * @param val_size size of @a val in bytes
  946. */
  947. struct GNUNET_GETOPT_CommandLineOption
  948. GNUNET_GETOPT_option_base32_fixed_size (char shortName,
  949. const char *name,
  950. const char *argumentHelp,
  951. const char *description,
  952. void *val,
  953. size_t val_size)
  954. {
  955. struct Base32Context *bc = GNUNET_new (struct Base32Context);
  956. struct GNUNET_GETOPT_CommandLineOption clo = {
  957. .shortName = shortName,
  958. .name = name,
  959. .argumentHelp = argumentHelp,
  960. .description = description,
  961. .require_argument = 1,
  962. .processor = &set_base32,
  963. .cleaner = &free_bc,
  964. .scls = (void *) bc
  965. };
  966. bc->val = val;
  967. bc->val_size = val_size;
  968. return clo;
  969. }
  970. /**
  971. * Make the given option mandatory.
  972. *
  973. * @param opt option to modify
  974. * @return @a opt with the mandatory flag set.
  975. */
  976. struct GNUNET_GETOPT_CommandLineOption
  977. GNUNET_GETOPT_option_mandatory (struct GNUNET_GETOPT_CommandLineOption opt)
  978. {
  979. opt.option_mandatory = 1;
  980. return opt;
  981. }
  982. /**
  983. * Make the given option mutually exclusive with other options.
  984. *
  985. * @param opt option to modify
  986. * @return @a opt with the exclusive flag set.
  987. */
  988. struct GNUNET_GETOPT_CommandLineOption
  989. GNUNET_GETOPT_option_exclusive (struct GNUNET_GETOPT_CommandLineOption opt)
  990. {
  991. opt.option_exclusive = 1;
  992. return opt;
  993. }
  994. /* end of getopt_helpers.c */