aboutsummaryrefslogtreecommitdiff
path: root/src/namestore
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-11-20 19:51:03 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-11-20 19:51:03 +0900
commit56a3e354dba3b348e508359af6b43160f99d7df3 (patch)
tree5fc0371a14e53e7432e6e7a1a4f754cd0283a69c /src/namestore
parentf2b264a16c3c9a4199876740a210496e63b0bea4 (diff)
downloadgnunet-56a3e354dba3b348e508359af6b43160f99d7df3.tar.gz
gnunet-56a3e354dba3b348e508359af6b43160f99d7df3.zip
NAMESTORE: CLI utility can now parse multiple records from stdin
Diffstat (limited to 'src/namestore')
-rw-r--r--src/namestore/gnunet-namestore.c846
1 files changed, 512 insertions, 334 deletions
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
index 36a0a9ba3..46012cf21 100644
--- a/src/namestore/gnunet-namestore.c
+++ b/src/namestore/gnunet-namestore.c
@@ -119,11 +119,6 @@ static struct GNUNET_NAMESTORE_Handle *ns;
119static struct GNUNET_IDENTITY_PrivateKey zone_pkey; 119static struct GNUNET_IDENTITY_PrivateKey zone_pkey;
120 120
121/** 121/**
122 * Handle to identity lookup.
123 */
124static struct GNUNET_IDENTITY_EgoLookup *el;
125
126/**
127 * Identity service handle 122 * Identity service handle
128 */ 123 */
129static struct GNUNET_IDENTITY_Handle *idh; 124static struct GNUNET_IDENTITY_Handle *idh;
@@ -168,6 +163,10 @@ static struct MarkedRecord *marked_head;
168 */ 163 */
169static struct MarkedRecord *marked_tail; 164static struct MarkedRecord *marked_tail;
170 165
166/**
167 * Configuration handle
168 */
169const struct GNUNET_CONFIGURATION_Handle *cfg;
171 170
172/** 171/**
173 * Ego list 172 * Ego list
@@ -190,6 +189,11 @@ static int list;
190static struct GNUNET_NAMESTORE_ZoneIterator *list_it; 189static struct GNUNET_NAMESTORE_ZoneIterator *list_it;
191 190
192/** 191/**
192 * Run in read from stdin mode.
193 */
194static int read_from_stdin;
195
196/**
193 * Desired action is to remove a record. 197 * Desired action is to remove a record.
194 */ 198 */
195static int del; 199static int del;
@@ -240,6 +244,11 @@ static struct GNUNET_NAMESTORE_QueueEntry *del_qe;
240static struct GNUNET_NAMESTORE_QueueEntry *set_qe; 244static struct GNUNET_NAMESTORE_QueueEntry *set_qe;
241 245
242/** 246/**
247 * Queue entry for begin/commit
248 */
249static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
250
251/**
243 * Name of the records to add/list/remove. 252 * Name of the records to add/list/remove.
244 */ 253 */
245static char *name; 254static char *name;
@@ -325,18 +334,217 @@ static struct RecordSetEntry *recordset;
325static struct GNUNET_SCHEDULER_Task *purge_task; 334static struct GNUNET_SCHEDULER_Task *purge_task;
326 335
327/** 336/**
328 * Task run on shutdown. Cleans up everything. 337 * Parse expiration time.
329 * 338 *
330 * @param cls unused 339 * @param expirationstring text to parse
340 * @param[out] etime_is_rel set to #GNUNET_YES if time is relative
341 * @param[out] etime set to expiration time (abs or rel)
342 * @return #GNUNET_OK on success
331 */ 343 */
344static int
345parse_expiration (const char *expirationstring,
346 int *etime_is_rel,
347 uint64_t *etime)
348{
349 struct GNUNET_TIME_Relative etime_rel;
350 struct GNUNET_TIME_Absolute etime_abs;
351
352 if (0 == strcmp (expirationstring, "never"))
353 {
354 *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
355 *etime_is_rel = GNUNET_NO;
356 return GNUNET_OK;
357 }
358 if (GNUNET_OK ==
359 GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
360 {
361 *etime_is_rel = GNUNET_YES;
362 *etime = etime_rel.rel_value_us;
363 if (GNUNET_TIME_relative_cmp (etime_rel, <, WARN_RELATIVE_EXPIRATION_LIMIT))
364 {
365 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
366 "Relative expiration times of less than %s are not recommended. To improve availability, consider increasing this value.\n",
367 GNUNET_STRINGS_relative_time_to_string (
368 WARN_RELATIVE_EXPIRATION_LIMIT, GNUNET_NO));
369 }
370 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
371 "Storing record with relative expiration time of %s\n",
372 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
373 return GNUNET_OK;
374 }
375 if (GNUNET_OK ==
376 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
377 {
378 *etime_is_rel = GNUNET_NO;
379 *etime = etime_abs.abs_value_us;
380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
381 "Storing record with absolute expiration time of %s\n",
382 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
383 return GNUNET_OK;
384 }
385 return GNUNET_SYSERR;
386}
387
388
389
390/**
391 * Command-line option parser function that allows the user to specify
392 * a complete record as one argument for adding/removing. A pointer
393 * to the head of the list of record sets must be passed as the "scls"
394 * argument.
395 *
396 * @param ctx command line processor context
397 * @param scls must be of type "struct GNUNET_FS_Uri **"
398 * @param option name of the option (typically 'R')
399 * @param value command line argument given; format is
400 * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs),
401 * always given in seconds (without the unit),
402 * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or
403 * a combination of 's' (shadow) and 'p' (public) and VALUE is the
404 * value (in human-readable format)
405 * @return #GNUNET_OK on success
406 */
407static int
408multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
409 void *scls,
410 const char *option,
411 const char *value)
412{
413 struct RecordSetEntry **head = scls;
414 struct RecordSetEntry *r;
415 struct GNUNET_GNSRECORD_Data record;
416 char *cp;
417 char *tok;
418 char *saveptr;
419 int etime_is_rel;
420 void *raw_data;
421
422 (void) ctx;
423 (void) option;
424 cp = GNUNET_strdup (value);
425 tok = strtok_r (cp, " ", &saveptr);
426 if (NULL == tok)
427 {
428 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
429 _ ("Empty record line argument is not allowed.\n"));
430 GNUNET_free (cp);
431 return GNUNET_SYSERR;
432 }
433 {
434 char *etime_in_s;
435
436 GNUNET_asprintf (&etime_in_s, "%s s", tok);
437 if (GNUNET_OK !=
438 parse_expiration (etime_in_s, &etime_is_rel, &record.expiration_time))
439 {
440 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
441 _ ("Invalid expiration time `%s' (must be without unit)\n"),
442 tok);
443 GNUNET_free (cp);
444 GNUNET_free (etime_in_s);
445 return GNUNET_SYSERR;
446 }
447 GNUNET_free (etime_in_s);
448 }
449 tok = strtok_r (NULL, " ", &saveptr);
450 if (NULL == tok)
451 {
452 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
453 _ ("Missing entries in record line `%s'.\n"),
454 value);
455 GNUNET_free (cp);
456 return GNUNET_SYSERR;
457 }
458 record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
459 if (UINT32_MAX == record.record_type)
460 {
461 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok);
462 GNUNET_free (cp);
463 return GNUNET_SYSERR;
464 }
465 tok = strtok_r (NULL, " ", &saveptr);
466 if (NULL == tok)
467 {
468 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
469 _ ("Missing entries in record line `%s'.\n"),
470 value);
471 GNUNET_free (cp);
472 return GNUNET_SYSERR;
473 }
474 record.flags = GNUNET_GNSRECORD_RF_NONE;
475 if (etime_is_rel)
476 record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
477 if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
478 record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
479 if (NULL != strchr (tok, (unsigned char) 's'))
480 record.flags |= GNUNET_GNSRECORD_RF_SHADOW;
481 /* find beginning of record value */
482 tok = strchr (&value[tok - cp], (unsigned char) ' ');
483 if (NULL == tok)
484 {
485 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
486 _ ("Missing entries in record line `%s'.\n"),
487 value);
488 GNUNET_free (cp);
489 return GNUNET_SYSERR;
490 }
491 GNUNET_free (cp);
492 tok++; /* skip space */
493 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type,
494 tok,
495 &raw_data,
496 &record.data_size))
497 {
498 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
499 _ ("Invalid record data for type %s: `%s'.\n"),
500 GNUNET_GNSRECORD_number_to_typename (record.record_type),
501 tok);
502 return GNUNET_SYSERR;
503 }
504
505 r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size);
506 r->next = *head;
507 record.data = &r[1];
508 memcpy (&r[1], raw_data, record.data_size);
509 GNUNET_free (raw_data);
510 r->record = record;
511 *head = r;
512 return GNUNET_OK;
513}
514
515/**
516 * Allow user to specify keywords.
517 *
518 * @param shortName short name of the option
519 * @param name long name of the option
520 * @param argumentHelp help text for the option argument
521 * @param description long help text for the option
522 * @param[out] topKeywords set to the desired value
523 */
524struct GNUNET_GETOPT_CommandLineOption
525multirecord_option (char shortName,
526 const char *name,
527 const char *argumentHelp,
528 const char *description,
529 struct RecordSetEntry **rs)
530{
531 struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName,
532 .name = name,
533 .argumentHelp = argumentHelp,
534 .description = description,
535 .require_argument = 1,
536 .processor =
537 &multirecord_process,
538 .scls = (void *) rs };
539
540 return clo;
541}
542
332static void 543static void
333do_shutdown (void *cls) 544reset_handles (void)
334{ 545{
335 struct EgoEntry *ego_entry;
336 struct EgoEntry *ego_tmp;
337 struct MarkedRecord *mrec; 546 struct MarkedRecord *mrec;
338 struct MarkedRecord *mrec_tmp; 547 struct MarkedRecord *mrec_tmp;
339 (void) cls;
340 if (NULL != ego_name) 548 if (NULL != ego_name)
341 { 549 {
342 GNUNET_free (ego_name); 550 GNUNET_free (ego_name);
@@ -347,16 +555,6 @@ do_shutdown (void *cls)
347 GNUNET_SCHEDULER_cancel (purge_task); 555 GNUNET_SCHEDULER_cancel (purge_task);
348 purge_task = NULL; 556 purge_task = NULL;
349 } 557 }
350 if (NULL != idh)
351 {
352 GNUNET_IDENTITY_disconnect (idh);
353 idh = NULL;
354 }
355 if (NULL != el)
356 {
357 GNUNET_IDENTITY_ego_lookup_cancel (el);
358 el = NULL;
359 }
360 for (mrec = marked_head; NULL != mrec;) 558 for (mrec = marked_head; NULL != mrec;)
361 { 559 {
362 mrec_tmp = mrec; 560 mrec_tmp = mrec;
@@ -364,13 +562,6 @@ do_shutdown (void *cls)
364 GNUNET_free (mrec_tmp->name); 562 GNUNET_free (mrec_tmp->name);
365 GNUNET_free (mrec_tmp); 563 GNUNET_free (mrec_tmp);
366 } 564 }
367 for (ego_entry = ego_head; NULL != ego_entry;)
368 {
369 ego_tmp = ego_entry;
370 ego_entry = ego_entry->next;
371 GNUNET_free (ego_tmp->identifier);
372 GNUNET_free (ego_tmp);
373 }
374 if (NULL != list_it) 565 if (NULL != list_it)
375 { 566 {
376 GNUNET_NAMESTORE_zone_iteration_stop (list_it); 567 GNUNET_NAMESTORE_zone_iteration_stop (list_it);
@@ -401,10 +592,10 @@ do_shutdown (void *cls)
401 GNUNET_NAMESTORE_cancel (del_qe); 592 GNUNET_NAMESTORE_cancel (del_qe);
402 del_qe = NULL; 593 del_qe = NULL;
403 } 594 }
404 if (NULL != ns) 595 if (NULL != reverse_qe)
405 { 596 {
406 GNUNET_NAMESTORE_disconnect (ns); 597 GNUNET_NAMESTORE_cancel (reverse_qe);
407 ns = NULL; 598 reverse_qe = NULL;
408 } 599 }
409 memset (&zone_pkey, 0, sizeof(zone_pkey)); 600 memset (&zone_pkey, 0, sizeof(zone_pkey));
410 if (NULL != uri) 601 if (NULL != uri)
@@ -425,15 +616,71 @@ do_shutdown (void *cls)
425} 616}
426 617
427 618
619
428/** 620/**
429 * Check if we are finished, and if so, perform shutdown. 621 * Task run on shutdown. Cleans up everything.
622 *
623 * @param cls unused
430 */ 624 */
431static void 625static void
432test_finished () 626do_shutdown (void *cls)
433{ 627{
434 if ((NULL == add_qe) && (NULL == add_qe_uri) && (NULL == get_qe) && 628 struct EgoEntry *ego_entry;
435 (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it)) 629 struct EgoEntry *ego_tmp;
436 GNUNET_SCHEDULER_shutdown (); 630 (void) cls;
631
632 reset_handles ();
633 if (NULL != ns_qe)
634 {
635 GNUNET_NAMESTORE_cancel (ns_qe);
636 ns_qe = NULL;
637 }
638 if (NULL != ns)
639 {
640 GNUNET_NAMESTORE_disconnect (ns);
641 ns = NULL;
642 }
643 if (NULL != idh)
644 {
645 GNUNET_IDENTITY_disconnect (idh);
646 idh = NULL;
647 }
648 for (ego_entry = ego_head; NULL != ego_entry;)
649 {
650 ego_tmp = ego_entry;
651 ego_entry = ego_entry->next;
652 GNUNET_free (ego_tmp->identifier);
653 GNUNET_free (ego_tmp);
654 }
655}
656
657static void
658commit_cb (void *cls, enum GNUNET_ErrorCode ec)
659{
660 ns_qe = NULL;
661 if (GNUNET_EC_NONE != ec)
662 {
663 fprintf (stderr, "Failed to commit to namestore: `%s'\n",
664 GNUNET_ErrorCode_get_hint (ec));
665 ret = 1;
666 }
667 GNUNET_SCHEDULER_shutdown ();
668}
669
670static void
671process_command_stdin ();
672
673
674static void
675finish_command (void)
676{
677 reset_handles ();
678 if (read_from_stdin)
679 {
680 process_command_stdin ();
681 return;
682 }
683 ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL);
437} 684}
438 685
439 686
@@ -452,7 +699,7 @@ add_continuation (void *cls, enum GNUNET_ErrorCode ec)
452 ret = 1; 699 ret = 1;
453 } 700 }
454 ret = 0; 701 ret = 0;
455 test_finished (); 702 finish_command ();
456} 703}
457 704
458 705
@@ -467,7 +714,7 @@ del_continuation (void *cls, enum GNUNET_ErrorCode ec)
467 _ ("Deleting record failed: %s\n"), GNUNET_ErrorCode_get_hint ( 714 _ ("Deleting record failed: %s\n"), GNUNET_ErrorCode_get_hint (
468 ec)); 715 ec));
469 } 716 }
470 test_finished (); 717 finish_command ();
471} 718}
472 719
473static void 720static void
@@ -496,7 +743,7 @@ purge_next_record (void *cls)
496 if (NULL == marked_head) 743 if (NULL == marked_head)
497 { 744 {
498 ret = 0; 745 ret = 0;
499 test_finished (); 746 finish_command ();
500 return; 747 return;
501 } 748 }
502 mrec = marked_head; 749 mrec = marked_head;
@@ -527,7 +774,7 @@ zone_iteration_finished (void *cls)
527 return; 774 return;
528 } 775 }
529 ret = 0; 776 ret = 0;
530 test_finished (); 777 finish_command ();
531} 778}
532 779
533 780
@@ -541,7 +788,7 @@ zone_iteration_error_cb (void *cls)
541 list_it = NULL; 788 list_it = NULL;
542 fprintf (stderr, "Error iterating over zone\n"); 789 fprintf (stderr, "Error iterating over zone\n");
543 ret = 1; 790 ret = 1;
544 test_finished (); 791 finish_command ();
545} 792}
546 793
547static void 794static void
@@ -797,7 +1044,7 @@ display_record_lookup (void *cls,
797 (void) zone_key; 1044 (void) zone_key;
798 get_qe = NULL; 1045 get_qe = NULL;
799 display_record (zone_key, rname, rd_len, rd); 1046 display_record (zone_key, rname, rd_len, rd);
800 test_finished (); 1047 finish_command ();
801} 1048}
802 1049
803 1050
@@ -838,7 +1085,7 @@ lookup_error_cb (void *cls)
838 (void) cls; 1085 (void) cls;
839 get_qe = NULL; 1086 get_qe = NULL;
840 fprintf (stderr, "%s", "Failed to lookup record.\n"); 1087 fprintf (stderr, "%s", "Failed to lookup record.\n");
841 test_finished (); 1088 finish_command ();
842} 1089}
843 1090
844 1091
@@ -852,7 +1099,7 @@ add_error_cb (void *cls)
852 add_qe = NULL; 1099 add_qe = NULL;
853 GNUNET_break (0); 1100 GNUNET_break (0);
854 ret = 1; 1101 ret = 1;
855 test_finished (); 1102 finish_command ();
856} 1103}
857 1104
858 1105
@@ -883,7 +1130,7 @@ get_existing_record (void *cls,
883 { 1130 {
884 GNUNET_break (0); 1131 GNUNET_break (0);
885 ret = 1; 1132 ret = 1;
886 test_finished (); 1133 finish_command ();
887 return; 1134 return;
888 } 1135 }
889 1136
@@ -904,7 +1151,7 @@ get_existing_record (void *cls,
904 "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"), 1151 "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"),
905 rec_name); 1152 rec_name);
906 ret = 1; 1153 ret = 1;
907 test_finished (); 1154 finish_command ();
908 return; 1155 return;
909 } 1156 }
910 break; 1157 break;
@@ -974,7 +1221,7 @@ handle_reverse_lookup (void *cls,
974 fprintf (stdout, "%s\n", reverse_pkey); 1221 fprintf (stdout, "%s\n", reverse_pkey);
975 else 1222 else
976 fprintf (stdout, "%s.%s\n", label, ego_name); 1223 fprintf (stdout, "%s.%s\n", label, ego_name);
977 test_finished (); 1224 finish_command ();
978} 1225}
979 1226
980 1227
@@ -988,7 +1235,7 @@ del_lookup_error_cb (void *cls)
988 del_qe = NULL; 1235 del_qe = NULL;
989 GNUNET_break (0); 1236 GNUNET_break (0);
990 ret = 1; 1237 ret = 1;
991 test_finished (); 1238 finish_command ();
992} 1239}
993 1240
994 1241
@@ -1025,7 +1272,7 @@ del_monitor (void *cls,
1025 "There are no records under label `%s' that could be deleted.\n"), 1272 "There are no records under label `%s' that could be deleted.\n"),
1026 label); 1273 label);
1027 ret = 1; 1274 ret = 1;
1028 test_finished (); 1275 finish_command ();
1029 return; 1276 return;
1030 } 1277 }
1031 if ((NULL == value) && (NULL == typestring)) 1278 if ((NULL == value) && (NULL == typestring))
@@ -1067,7 +1314,7 @@ del_monitor (void *cls,
1067 _ ( 1314 _ (
1068 "There are no records under label `%s' that match the request for deletion.\n"), 1315 "There are no records under label `%s' that match the request for deletion.\n"),
1069 label); 1316 label);
1070 test_finished (); 1317 finish_command ();
1071 return; 1318 return;
1072 } 1319 }
1073 /* delete everything but what we copied to 'rdx' */ 1320 /* delete everything but what we copied to 'rdx' */
@@ -1081,59 +1328,6 @@ del_monitor (void *cls,
1081} 1328}
1082 1329
1083 1330
1084/**
1085 * Parse expiration time.
1086 *
1087 * @param expirationstring text to parse
1088 * @param[out] etime_is_rel set to #GNUNET_YES if time is relative
1089 * @param[out] etime set to expiration time (abs or rel)
1090 * @return #GNUNET_OK on success
1091 */
1092static int
1093parse_expiration (const char *expirationstring,
1094 int *etime_is_rel,
1095 uint64_t *etime)
1096{
1097 struct GNUNET_TIME_Relative etime_rel;
1098 struct GNUNET_TIME_Absolute etime_abs;
1099
1100 if (0 == strcmp (expirationstring, "never"))
1101 {
1102 *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
1103 *etime_is_rel = GNUNET_NO;
1104 return GNUNET_OK;
1105 }
1106 if (GNUNET_OK ==
1107 GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
1108 {
1109 *etime_is_rel = GNUNET_YES;
1110 *etime = etime_rel.rel_value_us;
1111 if (GNUNET_TIME_relative_cmp (etime_rel, <, WARN_RELATIVE_EXPIRATION_LIMIT))
1112 {
1113 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1114 "Relative expiration times of less than %s are not recommended. To improve availability, consider increasing this value.\n",
1115 GNUNET_STRINGS_relative_time_to_string (
1116 WARN_RELATIVE_EXPIRATION_LIMIT, GNUNET_NO));
1117 }
1118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1119 "Storing record with relative expiration time of %s\n",
1120 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
1121 return GNUNET_OK;
1122 }
1123 if (GNUNET_OK ==
1124 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
1125 {
1126 *etime_is_rel = GNUNET_NO;
1127 *etime = etime_abs.abs_value_us;
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1129 "Storing record with absolute expiration time of %s\n",
1130 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
1131 return GNUNET_OK;
1132 }
1133 return GNUNET_SYSERR;
1134}
1135
1136
1137static void 1331static void
1138replace_cont (void *cls, enum GNUNET_ErrorCode ec) 1332replace_cont (void *cls, enum GNUNET_ErrorCode ec)
1139{ 1333{
@@ -1147,7 +1341,7 @@ replace_cont (void *cls, enum GNUNET_ErrorCode ec)
1147 GNUNET_ErrorCode_get_hint (ec)); 1341 GNUNET_ErrorCode_get_hint (ec));
1148 ret = 1; /* fail from 'main' */ 1342 ret = 1; /* fail from 'main' */
1149 } 1343 }
1150 GNUNET_SCHEDULER_shutdown (); 1344 finish_command ();
1151} 1345}
1152 1346
1153 1347
@@ -1173,14 +1367,7 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1173 { 1367 {
1174 /* nothing more to be done */ 1368 /* nothing more to be done */
1175 fprintf (stderr, _ ("No options given\n")); 1369 fprintf (stderr, _ ("No options given\n"));
1176 GNUNET_SCHEDULER_shutdown (); 1370 finish_command ();
1177 return;
1178 }
1179 ns = GNUNET_NAMESTORE_connect (cfg);
1180 if (NULL == ns)
1181 {
1182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1183 _ ("Failed to connect to namestore\n"));
1184 return; 1371 return;
1185 } 1372 }
1186 1373
@@ -1196,8 +1383,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1196 _ ("Missing option `%s' for operation `%s'\n"), 1383 _ ("Missing option `%s' for operation `%s'\n"),
1197 "-z", 1384 "-z",
1198 _ ("replace")); 1385 _ ("replace"));
1199 GNUNET_SCHEDULER_shutdown ();
1200 ret = 1; 1386 ret = 1;
1387 finish_command ();
1201 return; 1388 return;
1202 } 1389 }
1203 if (NULL == name) 1390 if (NULL == name)
@@ -1206,8 +1393,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1206 _ ("Missing option `%s' for operation `%s'\n"), 1393 _ ("Missing option `%s' for operation `%s'\n"),
1207 "-R", 1394 "-R",
1208 _ ("replace")); 1395 _ ("replace"));
1209 GNUNET_SCHEDULER_shutdown ();
1210 ret = 1; 1396 ret = 1;
1397 finish_command ();
1211 return; 1398 return;
1212 } 1399 }
1213 rd_count = 0; 1400 rd_count = 0;
@@ -1235,8 +1422,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1235 if (0 == strlen (nickstring)) 1422 if (0 == strlen (nickstring))
1236 { 1423 {
1237 fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring); 1424 fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring);
1238 GNUNET_SCHEDULER_shutdown ();
1239 ret = 1; 1425 ret = 1;
1426 finish_command ();
1240 return; 1427 return;
1241 } 1428 }
1242 add = 1; 1429 add = 1;
@@ -1258,8 +1445,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1258 _ ("Missing option `%s' for operation `%s'\n"), 1445 _ ("Missing option `%s' for operation `%s'\n"),
1259 "-z", 1446 "-z",
1260 _ ("add")); 1447 _ ("add"));
1261 GNUNET_SCHEDULER_shutdown ();
1262 ret = 1; 1448 ret = 1;
1449 finish_command ();
1263 return; 1450 return;
1264 } 1451 }
1265 if (NULL == name) 1452 if (NULL == name)
@@ -1268,8 +1455,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1268 _ ("Missing option `%s' for operation `%s'\n"), 1455 _ ("Missing option `%s' for operation `%s'\n"),
1269 "-n", 1456 "-n",
1270 _ ("add")); 1457 _ ("add"));
1271 GNUNET_SCHEDULER_shutdown ();
1272 ret = 1; 1458 ret = 1;
1459 finish_command ();
1273 return; 1460 return;
1274 } 1461 }
1275 if (NULL == typestring) 1462 if (NULL == typestring)
@@ -1278,16 +1465,16 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1278 _ ("Missing option `%s' for operation `%s'\n"), 1465 _ ("Missing option `%s' for operation `%s'\n"),
1279 "-t", 1466 "-t",
1280 _ ("add")); 1467 _ ("add"));
1281 GNUNET_SCHEDULER_shutdown ();
1282 ret = 1; 1468 ret = 1;
1469 finish_command ();
1283 return; 1470 return;
1284 } 1471 }
1285 type = GNUNET_GNSRECORD_typename_to_number (typestring); 1472 type = GNUNET_GNSRECORD_typename_to_number (typestring);
1286 if (UINT32_MAX == type) 1473 if (UINT32_MAX == type)
1287 { 1474 {
1288 fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring); 1475 fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring);
1289 GNUNET_SCHEDULER_shutdown ();
1290 ret = 1; 1476 ret = 1;
1477 finish_command ();
1291 return; 1478 return;
1292 } 1479 }
1293 if ((GNUNET_DNSPARSER_TYPE_SRV == type) || 1480 if ((GNUNET_DNSPARSER_TYPE_SRV == type) ||
@@ -1297,8 +1484,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1297 fprintf (stderr, 1484 fprintf (stderr,
1298 _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'")); 1485 _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"));
1299 fprintf (stderr, ", please use a `BOX' record instead\n"); 1486 fprintf (stderr, ", please use a `BOX' record instead\n");
1300 GNUNET_SCHEDULER_shutdown ();
1301 ret = 1; 1487 ret = 1;
1488 finish_command ();
1302 return; 1489 return;
1303 } 1490 }
1304 if (NULL == value) 1491 if (NULL == value)
@@ -1308,7 +1495,7 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1308 "-V", 1495 "-V",
1309 _ ("add")); 1496 _ ("add"));
1310 ret = 1; 1497 ret = 1;
1311 GNUNET_SCHEDULER_shutdown (); 1498 finish_command ();
1312 return; 1499 return;
1313 } 1500 }
1314 if (GNUNET_OK != 1501 if (GNUNET_OK !=
@@ -1318,8 +1505,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1318 _ ("Value `%s' invalid for record type `%s'\n"), 1505 _ ("Value `%s' invalid for record type `%s'\n"),
1319 value, 1506 value,
1320 typestring); 1507 typestring);
1321 GNUNET_SCHEDULER_shutdown ();
1322 ret = 1; 1508 ret = 1;
1509 finish_command ();
1323 return; 1510 return;
1324 } 1511 }
1325 if (NULL == expirationstring) 1512 if (NULL == expirationstring)
@@ -1328,15 +1515,15 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1328 _ ("Missing option `%s' for operation `%s'\n"), 1515 _ ("Missing option `%s' for operation `%s'\n"),
1329 "-e", 1516 "-e",
1330 _ ("add")); 1517 _ ("add"));
1331 GNUNET_SCHEDULER_shutdown ();
1332 ret = 1; 1518 ret = 1;
1519 finish_command ();
1333 return; 1520 return;
1334 } 1521 }
1335 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) 1522 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1336 { 1523 {
1337 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); 1524 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1338 GNUNET_SCHEDULER_shutdown ();
1339 ret = 1; 1525 ret = 1;
1526 finish_command ();
1340 return; 1527 return;
1341 } 1528 }
1342 add_qe = GNUNET_NAMESTORE_records_lookup (ns, 1529 add_qe = GNUNET_NAMESTORE_records_lookup (ns,
@@ -1355,8 +1542,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1355 _ ("Missing option `%s' for operation `%s'\n"), 1542 _ ("Missing option `%s' for operation `%s'\n"),
1356 "-z", 1543 "-z",
1357 _ ("del")); 1544 _ ("del"));
1358 GNUNET_SCHEDULER_shutdown ();
1359 ret = 1; 1545 ret = 1;
1546 finish_command ();
1360 return; 1547 return;
1361 } 1548 }
1362 if (NULL == name) 1549 if (NULL == name)
@@ -1365,8 +1552,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1365 _ ("Missing option `%s' for operation `%s'\n"), 1552 _ ("Missing option `%s' for operation `%s'\n"),
1366 "-n", 1553 "-n",
1367 _ ("del")); 1554 _ ("del"));
1368 GNUNET_SCHEDULER_shutdown ();
1369 ret = 1; 1555 ret = 1;
1556 finish_command ();
1370 return; 1557 return;
1371 } 1558 }
1372 del_qe = GNUNET_NAMESTORE_records_lookup (ns, 1559 del_qe = GNUNET_NAMESTORE_records_lookup (ns,
@@ -1398,8 +1585,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1398 _ ("Missing option `%s' for operation `%s'\n"), 1585 _ ("Missing option `%s' for operation `%s'\n"),
1399 "-z", 1586 "-z",
1400 _ ("purge-zone")); 1587 _ ("purge-zone"));
1401 GNUNET_SCHEDULER_shutdown ();
1402 ret = 1; 1588 ret = 1;
1589 finish_command ();
1403 return; 1590 return;
1404 } 1591 }
1405 list_it = GNUNET_NAMESTORE_zone_iteration_start2 (ns, 1592 list_it = GNUNET_NAMESTORE_zone_iteration_start2 (ns,
@@ -1423,8 +1610,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1423 _ ("Missing option `%s' for operation `%s'\n"), 1610 _ ("Missing option `%s' for operation `%s'\n"),
1424 "-z", 1611 "-z",
1425 _ ("list")); 1612 _ ("list"));
1426 GNUNET_SCHEDULER_shutdown ();
1427 ret = 1; 1613 ret = 1;
1614 finish_command ();
1428 return; 1615 return;
1429 } 1616 }
1430 get_qe = GNUNET_NAMESTORE_records_lookup (ns, 1617 get_qe = GNUNET_NAMESTORE_records_lookup (ns,
@@ -1457,8 +1644,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1457 _ ("Missing option `%s' for operation `%s'\n"), 1644 _ ("Missing option `%s' for operation `%s'\n"),
1458 "-z", 1645 "-z",
1459 _ ("reverse-pkey")); 1646 _ ("reverse-pkey"));
1460 GNUNET_SCHEDULER_shutdown ();
1461 ret = 1; 1647 ret = 1;
1648 finish_command ();
1462 return; 1649 return;
1463 } 1650 }
1464 if (GNUNET_OK != 1651 if (GNUNET_OK !=
@@ -1468,7 +1655,9 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1468 fprintf (stderr, 1655 fprintf (stderr,
1469 _ ("Invalid public key for reverse lookup `%s'\n"), 1656 _ ("Invalid public key for reverse lookup `%s'\n"),
1470 reverse_pkey); 1657 reverse_pkey);
1471 GNUNET_SCHEDULER_shutdown (); 1658 ret = 1;
1659 finish_command ();
1660 return;
1472 } 1661 }
1473 reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns, 1662 reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns,
1474 &zone_pkey, 1663 &zone_pkey,
@@ -1489,8 +1678,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1489 _ ("Missing option `%s' for operation `%s'\n"), 1678 _ ("Missing option `%s' for operation `%s'\n"),
1490 "-z", 1679 "-z",
1491 _ ("uri")); 1680 _ ("uri"));
1492 GNUNET_SCHEDULER_shutdown ();
1493 ret = 1; 1681 ret = 1;
1682 finish_command ();
1494 return; 1683 return;
1495 } 1684 }
1496 1685
@@ -1502,8 +1691,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1502 GNUNET_IDENTITY_public_key_from_string (sh, &pkey))) 1691 GNUNET_IDENTITY_public_key_from_string (sh, &pkey)))
1503 { 1692 {
1504 fprintf (stderr, _ ("Invalid URI `%s'\n"), uri); 1693 fprintf (stderr, _ ("Invalid URI `%s'\n"), uri);
1505 GNUNET_SCHEDULER_shutdown ();
1506 ret = 1; 1694 ret = 1;
1695 finish_command ();
1507 return; 1696 return;
1508 } 1697 }
1509 if (NULL == expirationstring) 1698 if (NULL == expirationstring)
@@ -1512,15 +1701,15 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1512 _ ("Missing option `%s' for operation `%s'\n"), 1701 _ ("Missing option `%s' for operation `%s'\n"),
1513 "-e", 1702 "-e",
1514 _ ("add")); 1703 _ ("add"));
1515 GNUNET_SCHEDULER_shutdown ();
1516 ret = 1; 1704 ret = 1;
1705 finish_command ();
1517 return; 1706 return;
1518 } 1707 }
1519 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) 1708 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1520 { 1709 {
1521 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); 1710 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1522 GNUNET_SCHEDULER_shutdown ();
1523 ret = 1; 1711 ret = 1;
1712 finish_command ();
1524 return; 1713 return;
1525 } 1714 }
1526 memset (&rd, 0, sizeof(rd)); 1715 memset (&rd, 0, sizeof(rd));
@@ -1556,34 +1745,182 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1556 } 1745 }
1557} 1746}
1558 1747
1748#define MAX_LINE_LEN 4086
1749
1750#define MAX_ARGS 20
1559 1751
1560/**
1561 * Callback invoked from identity service with ego information.
1562 * An @a ego of NULL means the ego was not found.
1563 *
1564 * @param cls closure with the configuration
1565 * @param ego an ego known to identity service, or NULL
1566 */
1567static void 1752static void
1568identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) 1753process_command_stdin ()
1569{ 1754{
1570 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 1755 struct EgoEntry *ego_entry;
1756 char buf[MAX_LINE_LEN];
1757 char *tmp_argv[MAX_ARGS];
1758 unsigned int tmp_argc = 0;
1759 char *tmp;
1760 struct GNUNET_GETOPT_CommandLineOption options[] =
1761 { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add),
1762 GNUNET_GETOPT_option_flag ('d',
1763 "delete",
1764 gettext_noop ("delete record"),
1765 &del),
1766 GNUNET_GETOPT_option_flag ('D',
1767 "display",
1768 gettext_noop ("display records"),
1769 &list),
1770 GNUNET_GETOPT_option_flag ('S',
1771 "from-stdin",
1772 gettext_noop ("read commands from stdin"),
1773 &read_from_stdin),
1774 GNUNET_GETOPT_option_string (
1775 'e',
1776 "expiration",
1777 "TIME",
1778 gettext_noop (
1779 "expiration time for record to use (for adding only), \"never\" is possible"),
1780 &expirationstring),
1781 GNUNET_GETOPT_option_string ('i',
1782 "nick",
1783 "NICKNAME",
1784 gettext_noop (
1785 "set the desired nick name for the zone"),
1786 &nickstring),
1787 GNUNET_GETOPT_option_flag ('m',
1788 "monitor",
1789 gettext_noop (
1790 "monitor changes in the namestore"),
1791 &monitor),
1792 GNUNET_GETOPT_option_string ('n',
1793 "name",
1794 "NAME",
1795 gettext_noop (
1796 "name of the record to add/delete/display"),
1797 &name),
1798 GNUNET_GETOPT_option_string ('r',
1799 "reverse",
1800 "PKEY",
1801 gettext_noop (
1802 "determine our name for the given PKEY"),
1803 &reverse_pkey),
1804 multirecord_option (
1805 'R',
1806 "replace",
1807 "RECORDLINE",
1808 gettext_noop (
1809 "set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"),
1810 &recordset),
1811 GNUNET_GETOPT_option_string ('t',
1812 "type",
1813 "TYPE",
1814 gettext_noop (
1815 "type of the record to add/delete/display"),
1816 &typestring),
1817 GNUNET_GETOPT_option_string ('u',
1818 "uri",
1819 "URI",
1820 gettext_noop ("URI to import into our zone"),
1821 &uri),
1822 GNUNET_GETOPT_option_string ('V',
1823 "value",
1824 "VALUE",
1825 gettext_noop (
1826 "value of the record to add/delete"),
1827 &value),
1828 GNUNET_GETOPT_option_flag ('p',
1829 "public",
1830 gettext_noop ("create or list public record"),
1831 &is_public),
1832 GNUNET_GETOPT_option_flag ('o',
1833 "omit-private",
1834 gettext_noop ("omit private records"),
1835 &omit_private),
1836 GNUNET_GETOPT_option_flag ('T',
1837 "include-maintenance",
1838 gettext_noop (
1839 "do not filter maintenance records"),
1840 &include_maintenance),
1841 GNUNET_GETOPT_option_flag ('P',
1842 "purge-orphans",
1843 gettext_noop (
1844 "purge namestore of all orphans"),
1845 &purge_orphaned),
1846 GNUNET_GETOPT_option_flag ('O',
1847 "list-orphans",
1848 gettext_noop (
1849 "show private key for orphaned records for recovery using `gnunet-identity -C -P <key>'. Use in combination with --display"),
1850 &list_orphaned),
1851 GNUNET_GETOPT_option_flag ('X',
1852 "purge-zone-records",
1853 gettext_noop (
1854 "delete all records in specified zone"),
1855 &purge_zone),
1856 GNUNET_GETOPT_option_flag (
1857 's',
1858 "shadow",
1859 gettext_noop (
1860 "create shadow record (only valid if all other records of the same type have expired"),
1861 &is_shadow),
1862 GNUNET_GETOPT_option_string ('z',
1863 "zone",
1864 "EGO",
1865 gettext_noop (
1866 "name of the ego controlling the zone"),
1867 &ego_name),
1868 GNUNET_GETOPT_OPTION_END };
1571 1869
1572 el = NULL;
1573 1870
1574 if (NULL == ego) 1871 if (NULL == fgets (buf, sizeof (buf), stdin))
1575 { 1872 {
1576 if (NULL != ego_name) 1873 ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL);
1577 { 1874 return;
1578 fprintf (stderr, 1875 }
1579 _ ("Ego `%s' not known to identity service\n"), 1876 if (buf[strlen (buf) - 1] == '\n')
1580 ego_name); 1877 buf[strlen (buf) - 1] = '\0';
1581 } 1878 /* We need to build a char *const *argv here */
1879 /* I guess strtok on space */
1880 tmp = strtok (buf, " ");
1881 if (NULL == tmp)
1882 {
1883 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1884 "Error parsing line %s\n", buf);
1582 GNUNET_SCHEDULER_shutdown (); 1885 GNUNET_SCHEDULER_shutdown ();
1583 ret = -1;
1584 return; 1886 return;
1585 } 1887 }
1586 zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); 1888 tmp_argv[0] = tmp;
1889 tmp_argc = 1;
1890 while (NULL != (tmp = strtok (NULL, " ")))
1891 {
1892 tmp_argv[tmp_argc] = tmp;
1893 tmp_argc++;
1894 }
1895 GNUNET_GETOPT_run ("gnunet-namestore", options, tmp_argc, tmp_argv);
1896 for (ego_entry = ego_head; NULL != ego_entry; ego_entry = ego_entry->next)
1897 {
1898 if (0 != strcmp (ego_entry->identifier, ego_name))
1899 continue;
1900 zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1901 break;
1902 }
1903 run_with_zone_pkey (cfg);
1904}
1905
1906
1907static void
1908begin_cb (void *cls, enum GNUNET_ErrorCode ec)
1909{
1910 ns_qe = NULL;
1911 if (GNUNET_EC_NONE != ec)
1912 {
1913 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1914 "Failed to start transaction: %s\n",
1915 GNUNET_ErrorCode_get_hint (ec));
1916 GNUNET_SCHEDULER_shutdown ();
1917 return;
1918 }
1919 if (read_from_stdin)
1920 {
1921 process_command_stdin ();
1922 return;
1923 }
1587 run_with_zone_pkey (cfg); 1924 run_with_zone_pkey (cfg);
1588} 1925}
1589 1926
@@ -1606,7 +1943,6 @@ id_connect_cb (void *cls,
1606 void **ctx, 1943 void **ctx,
1607 const char *name) 1944 const char *name)
1608{ 1945{
1609 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1610 struct GNUNET_IDENTITY_PublicKey pk; 1946 struct GNUNET_IDENTITY_PublicKey pk;
1611 struct EgoEntry *ego_entry; 1947 struct EgoEntry *ego_entry;
1612 1948
@@ -1621,17 +1957,20 @@ id_connect_cb (void *cls,
1621 GNUNET_CONTAINER_DLL_insert_tail (ego_head, 1957 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1622 ego_tail, 1958 ego_tail,
1623 ego_entry); 1959 ego_entry);
1960 if ((NULL != ego_name) &&
1961 (0 == strcmp (name, ego_name)))
1962 zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
1624 return; 1963 return;
1625 } 1964 }
1626 if (NULL != ego) 1965 if (NULL != ego)
1627 return; 1966 return;
1628 if (NULL == ego_name) 1967 ns_qe = GNUNET_NAMESTORE_transaction_begin (ns, &begin_cb, (void *) cfg);
1629 run_with_zone_pkey (cfg);
1630 else
1631 el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg);
1632} 1968}
1633 1969
1634 1970
1971
1972
1973
1635/** 1974/**
1636 * Main function that will be run. 1975 * Main function that will be run.
1637 * 1976 *
@@ -1644,202 +1983,36 @@ static void
1644run (void *cls, 1983run (void *cls,
1645 char *const *args, 1984 char *const *args,
1646 const char *cfgfile, 1985 const char *cfgfile,
1647 const struct GNUNET_CONFIGURATION_Handle *cfg) 1986 const struct GNUNET_CONFIGURATION_Handle *_cfg)
1648{ 1987{
1649 const char *pkey_str;
1650
1651 (void) cls; 1988 (void) cls;
1652 (void) args; 1989 (void) args;
1653 (void) cfgfile; 1990 (void) cfgfile;
1991 cfg = _cfg;
1654 if (NULL != args[0]) 1992 if (NULL != args[0])
1655 GNUNET_log ( 1993 GNUNET_log (
1656 GNUNET_ERROR_TYPE_WARNING, 1994 GNUNET_ERROR_TYPE_WARNING,
1657 _ ("Superfluous command line arguments (starting with `%s') ignored\n"), 1995 _ ("Superfluous command line arguments (starting with `%s') ignored\n"),
1658 args[0]); 1996 args[0]);
1659 if ((NULL != args[0]) && (NULL == uri))
1660 uri = GNUNET_strdup (args[0]);
1661 1997
1662 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg); 1998 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg);
1663 pkey_str = getenv ("GNUNET_NAMESTORE_EGO_PRIVATE_KEY"); 1999 ns = GNUNET_NAMESTORE_connect (cfg);
1664 if (NULL != pkey_str) 2000 if (NULL == ns)
1665 { 2001 {
1666 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pkey_str, 2002 fprintf (stderr, _ ("Failed to connect to namestore\n"));
1667 strlen (pkey_str), 2003 GNUNET_SCHEDULER_shutdown ();
1668 &zone_pkey,
1669 sizeof(zone_pkey)))
1670 {
1671 fprintf (stderr,
1672 "Malformed private key `%s' in $%s\n",
1673 pkey_str,
1674 "GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
1675 ret = 1;
1676 GNUNET_SCHEDULER_shutdown ();
1677 return;
1678 }
1679 run_with_zone_pkey (cfg);
1680 return; 2004 return;
1681 } 2005 }
1682 idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg); 2006 idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg);
1683 if (NULL == idh) 2007 if (NULL == idh)
1684 fprintf (stderr, _ ("Cannot connect to identity service\n"));
1685 ret = -1;
1686}
1687
1688
1689/**
1690 * Command-line option parser function that allows the user to specify
1691 * a complete record as one argument for adding/removing. A pointer
1692 * to the head of the list of record sets must be passed as the "scls"
1693 * argument.
1694 *
1695 * @param ctx command line processor context
1696 * @param scls must be of type "struct GNUNET_FS_Uri **"
1697 * @param option name of the option (typically 'R')
1698 * @param value command line argument given; format is
1699 * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs),
1700 * always given in seconds (without the unit),
1701 * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or
1702 * a combination of 's' (shadow) and 'p' (public) and VALUE is the
1703 * value (in human-readable format)
1704 * @return #GNUNET_OK on success
1705 */
1706static int
1707multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
1708 void *scls,
1709 const char *option,
1710 const char *value)
1711{
1712 struct RecordSetEntry **head = scls;
1713 struct RecordSetEntry *r;
1714 struct GNUNET_GNSRECORD_Data record;
1715 char *cp;
1716 char *tok;
1717 char *saveptr;
1718 int etime_is_rel;
1719 void *raw_data;
1720
1721 (void) ctx;
1722 (void) option;
1723 cp = GNUNET_strdup (value);
1724 tok = strtok_r (cp, " ", &saveptr);
1725 if (NULL == tok)
1726 {
1727 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1728 _ ("Empty record line argument is not allowed.\n"));
1729 GNUNET_free (cp);
1730 return GNUNET_SYSERR;
1731 }
1732 { 2008 {
1733 char *etime_in_s; 2009 ret = -1;
1734 2010 fprintf (stderr, _ ("Cannot connect to identity service\n"));
1735 GNUNET_asprintf (&etime_in_s, "%s s", tok); 2011 GNUNET_SCHEDULER_shutdown ();
1736 if (GNUNET_OK !=
1737 parse_expiration (etime_in_s, &etime_is_rel, &record.expiration_time))
1738 {
1739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1740 _ ("Invalid expiration time `%s' (must be without unit)\n"),
1741 tok);
1742 GNUNET_free (cp);
1743 GNUNET_free (etime_in_s);
1744 return GNUNET_SYSERR;
1745 }
1746 GNUNET_free (etime_in_s);
1747 }
1748 tok = strtok_r (NULL, " ", &saveptr);
1749 if (NULL == tok)
1750 {
1751 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1752 _ ("Missing entries in record line `%s'.\n"),
1753 value);
1754 GNUNET_free (cp);
1755 return GNUNET_SYSERR;
1756 }
1757 record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
1758 if (UINT32_MAX == record.record_type)
1759 {
1760 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok);
1761 GNUNET_free (cp);
1762 return GNUNET_SYSERR;
1763 }
1764 tok = strtok_r (NULL, " ", &saveptr);
1765 if (NULL == tok)
1766 {
1767 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1768 _ ("Missing entries in record line `%s'.\n"),
1769 value);
1770 GNUNET_free (cp);
1771 return GNUNET_SYSERR;
1772 }
1773 record.flags = GNUNET_GNSRECORD_RF_NONE;
1774 if (etime_is_rel)
1775 record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1776 if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
1777 record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1778 if (NULL != strchr (tok, (unsigned char) 's'))
1779 record.flags |= GNUNET_GNSRECORD_RF_SHADOW;
1780 /* find beginning of record value */
1781 tok = strchr (&value[tok - cp], (unsigned char) ' ');
1782 if (NULL == tok)
1783 {
1784 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1785 _ ("Missing entries in record line `%s'.\n"),
1786 value);
1787 GNUNET_free (cp);
1788 return GNUNET_SYSERR;
1789 }
1790 GNUNET_free (cp);
1791 tok++; /* skip space */
1792 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type,
1793 tok,
1794 &raw_data,
1795 &record.data_size))
1796 {
1797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1798 _ ("Invalid record data for type %s: `%s'.\n"),
1799 GNUNET_GNSRECORD_number_to_typename (record.record_type),
1800 tok);
1801 return GNUNET_SYSERR;
1802 } 2012 }
1803
1804 r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size);
1805 r->next = *head;
1806 record.data = &r[1];
1807 memcpy (&r[1], raw_data, record.data_size);
1808 GNUNET_free (raw_data);
1809 r->record = record;
1810 *head = r;
1811 return GNUNET_OK;
1812} 2013}
1813 2014
1814 2015
1815/**
1816 * Allow user to specify keywords.
1817 *
1818 * @param shortName short name of the option
1819 * @param name long name of the option
1820 * @param argumentHelp help text for the option argument
1821 * @param description long help text for the option
1822 * @param[out] topKeywords set to the desired value
1823 */
1824struct GNUNET_GETOPT_CommandLineOption
1825multirecord_option (char shortName,
1826 const char *name,
1827 const char *argumentHelp,
1828 const char *description,
1829 struct RecordSetEntry **rs)
1830{
1831 struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName,
1832 .name = name,
1833 .argumentHelp = argumentHelp,
1834 .description = description,
1835 .require_argument = 1,
1836 .processor =
1837 &multirecord_process,
1838 .scls = (void *) rs };
1839
1840 return clo;
1841}
1842
1843 2016
1844/** 2017/**
1845 * The main function for gnunet-namestore. 2018 * The main function for gnunet-namestore.
@@ -1851,6 +2024,7 @@ multirecord_option (char shortName,
1851int 2024int
1852main (int argc, char *const *argv) 2025main (int argc, char *const *argv)
1853{ 2026{
2027 int lret;
1854 struct GNUNET_GETOPT_CommandLineOption options[] = 2028 struct GNUNET_GETOPT_CommandLineOption options[] =
1855 { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add), 2029 { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add),
1856 GNUNET_GETOPT_option_flag ('d', 2030 GNUNET_GETOPT_option_flag ('d',
@@ -1861,6 +2035,10 @@ main (int argc, char *const *argv)
1861 "display", 2035 "display",
1862 gettext_noop ("display records"), 2036 gettext_noop ("display records"),
1863 &list), 2037 &list),
2038 GNUNET_GETOPT_option_flag ('S',
2039 "from-stdin",
2040 gettext_noop ("read commands from stdin"),
2041 &read_from_stdin),
1864 GNUNET_GETOPT_option_string ( 2042 GNUNET_GETOPT_option_string (
1865 'e', 2043 'e',
1866 "expiration", 2044 "expiration",
@@ -1956,7 +2134,7 @@ main (int argc, char *const *argv)
1956 "name of the ego controlling the zone"), 2134 "name of the ego controlling the zone"),
1957 &ego_name), 2135 &ego_name),
1958 GNUNET_GETOPT_OPTION_END }; 2136 GNUNET_GETOPT_OPTION_END };
1959 int lret; 2137
1960 2138
1961 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 2139 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1962 return 2; 2140 return 2;