gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated: New version of `gnunet-search` is ready


From: gnunet
Subject: [gnunet] branch master updated: New version of `gnunet-search` is ready to be tested
Date: Thu, 10 Feb 2022 23:24:58 +0100

This is an automated email from the git hooks/post-receive script.

madmurphy pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 4b887d8a8 New version of `gnunet-search` is ready to be tested
4b887d8a8 is described below

commit 4b887d8a8a849a8c878934009976dd47300b43cb
Author: madmurphy <madmurphy333@gmail.com>
AuthorDate: Thu Feb 10 22:24:56 2022 +0000

    New version of `gnunet-search` is ready to be tested
---
 src/fs/gnunet-search.c | 616 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 524 insertions(+), 92 deletions(-)

diff --git a/src/fs/gnunet-search.c b/src/fs/gnunet-search.c
index 3bf013650..124a0a1a4 100644
--- a/src/fs/gnunet-search.c
+++ b/src/fs/gnunet-search.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 GNUnet e.V.
+     Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009, 2022 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -24,10 +24,57 @@
  * @author Krista Bennett
  * @author James Blackwell
  * @author Igor Wronsky
+ * @author madmurphy
  */
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
 #include "platform.h"
 #include "gnunet_fs_service.h"
 
+
+#define GNUNET_SEARCH_log(kind, ...) \
+       GNUNET_log_from(kind, "gnunet-search", __VA_ARGS__)
+
+
+/*  The default settings that we use for the printed output  */
+
+#define DEFAULT_DIR_FORMAT       "#%n:\ngnunet-download -o \"%f\" -R %u\n\n"
+#define HELP_DEFAULT_DIR_FORMAT  "#%n:\\ngnunet-download -o \"%f\" -R %u\\n\\n"
+#define DEFAULT_FILE_FORMAT      "#%n:\ngnunet-download -o \"%f\" %u\n\n"
+#define HELP_DEFAULT_FILE_FORMAT "#%n:\\ngnunet-download -o \"%f\" %u\\n\\n"
+#define VERB_DEFAULT_DIR_FORMAT  DEFAULT_DIR_FORMAT "%a\n"
+#define VERB_DEFAULT_FILE_FORMAT DEFAULT_FILE_FORMAT "%a\n"
+
+#if HAVE_LIBEXTRACTOR
+#define DEFAULT_META_FORMAT      "  %t: %p\n"
+#define HELP_DEFAULT_META_FORMAT "  %t: %p\\n"
+#define HELP_EXTRACTOR_TEXTADD   ", %t is the property type"
+#else
+#define DEFAULT_META_FORMAT      "  MetaType #%i: %p\n"
+#define HELP_DEFAULT_META_FORMAT "  MetaType #%i: %p\\n"
+#define HELP_EXTRACTOR_TEXTADD   ""
+#endif
+
+#define GENERIC_DIRECTORY_NAME   "collection"
+#define GENERIC_FILE_NAME        "no-name"
+#define GENERIC_FILE_MIMETYPE    "application/octet-stream"
+
+
+enum GNUNET_SEARCH_MetadataPrinterFlags {
+  METADATA_PRINTER_FLAG_NONE = 0,
+  METADATA_PRINTER_FLAG_ONE_RUN = 1,
+  METADATA_PRINTER_FLAG_HAVE_TYPE = 2
+};
+
+
+struct GNUNET_SEARCH_MetadataPrinterInfo {
+  unsigned int counter;
+  unsigned int flags;
+  int type;
+};
+
+
 static int ret;
 
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -38,6 +85,12 @@ static struct GNUNET_FS_SearchContext *sc;
 
 static char *output_filename;
 
+static char *format_string;
+
+static char *dir_format_string;
+
+static char *meta_format_string;
+
 static struct GNUNET_FS_DirectoryBuilder *db;
 
 static unsigned int anonymity = 1;
@@ -53,16 +106,79 @@ static unsigned int results;
 
 static unsigned int verbose;
 
+static int bookmark_only;
+
 static int local_only;
 
+static int silent_mode;
+
 static struct GNUNET_SCHEDULER_Task *tt;
 
 
+/**
+ * Print the escape sequence at the beginning of a string.
+ *
+ * @param esc a string that **must** begin with a backslash (the function only
+ *        assumes that it does, but does not check)
+ * @return the fragment that follows what has been printed
+ * @author madmurphy
+ *
+ * If `"\\nfoo"` is passed as argument, this function prints a new line and
+ * returns `"foo"`
+ */
+static const char *
+print_escape_sequence (const char *const esc)
+{
+  unsigned int probe;
+  const char * cursor = esc + 1;
+  char tmp;
+  switch (*cursor)
+  {
+  /*  Trivia  */
+  case '\\': putchar ('\\'); return cursor + 1;
+  case 'a': putchar ('\a'); return cursor + 1;
+  case 'b': putchar ('\b'); return cursor + 1;
+  case 'e': putchar ('\x1B'); return cursor + 1;
+  case 'f': putchar ('\f'); return cursor + 1;
+  case 'n': putchar ('\n'); return cursor + 1;
+  case 'r': putchar ('\r'); return cursor + 1;
+  case 't': putchar ('\t'); return cursor + 1;
+  case 'v': putchar ('\v'); return cursor + 1;
+
+  /*  Possibly hexadecimal code point  */
+  case 'x':
+    probe = 0;
+    while (probe < 256 && isxdigit((tmp = *++cursor)))
+      probe = (probe << 4) + tmp - (tmp > 96 ? 87 : tmp > 64 ? 55 : 48);
+    goto maybe_codepoint;
+
+  /*  Possibly octal code point  */
+  case '0': case '1': case '2': case '3':
+  case '4': case '5': case '6': case '7':
+    probe = *cursor++ - 48;
+    do probe = (probe << 3) + *cursor++ - 48;
+    while (probe < 256 && cursor < esc + 4 && *cursor > 47 && *cursor < 56);
+    goto maybe_codepoint;
+
+  /*  Boredom  */
+  case '\0': putchar ('\\'); return cursor;
+  default: printf ("\\%c", *cursor); return cursor + 1;
+  }
+
+maybe_codepoint:
+  if (probe < 256)
+    putchar (probe);
+  else
+    fwrite (esc, 1, cursor - esc, stdout);
+  return cursor;
+}
+
+
 /**
  * Type of a function that libextractor calls for each
  * meta data item found.
  *
- * @param cls closure (user-defined, unused)
+ * @param cls closure (user-defined, used for the iteration info)
  * @param plugin_name name of the plugin that produced this value;
  *        special values can be used (e.g. '&lt;zlib&gt;' for zlib being
  *        used in the main libextractor library and yielding
@@ -76,33 +192,228 @@ static struct GNUNET_SCHEDULER_Task *tt;
  * @return 0 to continue extracting, 1 to abort
  */
 static int
-item_printer (void *cls,
-              const char *plugin_name,
-              enum EXTRACTOR_MetaType type,
-              enum EXTRACTOR_MetaFormat format,
-              const char *data_mime_type,
-              const char *data,
-              size_t data_size)
+item_printer (void *const cls,
+              const char *const plugin_name,
+              const enum EXTRACTOR_MetaType type,
+              const enum EXTRACTOR_MetaFormat format,
+              const char *const data_mime_type,
+              const char *const data,
+              const size_t data_size)
 {
-  if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
-      (format != EXTRACTOR_METAFORMAT_C_STRING))
+#define info ((struct GNUNET_SEARCH_MetadataPrinterInfo *) cls)
+  if ((format != EXTRACTOR_METAFORMAT_UTF8 &&
+       format != EXTRACTOR_METAFORMAT_C_STRING) ||
+      type == EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME)
     return 0;
-  if (type == EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME)
+  info->counter++;
+  if ((info->flags & METADATA_PRINTER_FLAG_HAVE_TYPE) && type != info->type)
     return 0;
+
+  const char *cursor = meta_format_string;
+  const char *next_spec = strchr(cursor, '%');
+  const char *next_esc = strchr(cursor, '\\');
+
+parse_format:
+
+  /*  If an escape sequence exists before the next format specifier...  */
+  if (next_esc && (!next_spec || next_esc < next_spec))
+  {
+    if (next_esc > cursor)
+      fwrite (cursor, 1, next_esc - cursor, stdout);
+
+    cursor = print_escape_sequence (next_esc);
+    next_esc = strchr(cursor, '\\');
+    goto parse_format;
+  }
+
+  /*  If a format specifier exists before the next escape sequence...  */
+  if (next_spec && (!next_esc || next_spec < next_esc))
+  {
+    if (next_spec > cursor)
+      fwrite (cursor, 1, next_spec - cursor, stdout);
+
+    switch (*++next_spec)
+    {
+    case '%': putchar('%'); break;
+    case 'i': printf ("%d", type); break;
+    case 'l': printf ("%lu", (long unsigned int) data_size); break;
+    case 'n': printf ("%u", info->counter); break;
+    case 'p': printf ("%s", data); break;
 #if HAVE_LIBEXTRACTOR
-  printf ("\t%20s: %s\n",
-          dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN,
-                    EXTRACTOR_metatype_to_string (type)),
-          data);
-#else
-  printf ("\t%20d: %s\n", type, data);
+    case 't':
+      printf ("%s",
+              dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN,
+                        EXTRACTOR_metatype_to_string (type)));
+      break;
 #endif
-  return 0;
+    case 'w': printf ("%s", plugin_name); break;
+    case '\0': putchar('%'); return 0;
+    default: printf ("%%%c", *next_spec); break;
+    }
+    cursor = next_spec + 1;
+    next_spec = strchr(cursor, '%');
+    goto parse_format;
+  }
+
+  if (*cursor)
+    printf ("%s", cursor);
+
+  return info->flags & METADATA_PRINTER_FLAG_ONE_RUN;
+#undef info
+}
+
+
+/**
+ * Print a search result according to the current formats
+ *
+ * @param filename the filename for this result
+ * @param uri the `struct GNUNET_FS_Uri` this result refers to
+ * @param metadata the `struct GNUNET_CONTAINER_MetaData` associated with this
+          result
+ * @param resultnum the result number
+ * @param is_directory GNUNET_YES if this is a directory, otherwise GNUNET_NO
+ * @author madmurphy
+ */
+static void
+print_search_result (const char *const filename,
+                     const struct GNUNET_FS_Uri *const uri,
+                     const struct GNUNET_CONTAINER_MetaData *const metadata,
+                     const unsigned int resultnum,
+                     const int is_directory)
+{
+
+  const char *cursor = GNUNET_YES == is_directory ?
+                         dir_format_string
+                       : format_string;
+
+  const char *next_spec = strchr(cursor, '%');
+  const char *next_esc = strchr(cursor, '\\');
+  char *placeholder;
+  struct GNUNET_SEARCH_MetadataPrinterInfo info;
+
+parse_format:
+  /*  If an escape sequence exists before the next format specifier...  */
+  if (next_esc && (!next_spec || next_esc < next_spec))
+  {
+    if (next_esc > cursor)
+      fwrite (cursor, 1, next_esc - cursor, stdout);
+
+    cursor = print_escape_sequence (next_esc);
+    next_esc = strchr(cursor, '\\');
+    goto parse_format;
+  }
+
+  /*  If a format specifier exists before the next escape sequence...  */
+  if (next_spec && (!next_esc || next_spec < next_esc))
+  {
+    if (next_spec > cursor)
+      fwrite (cursor, 1, next_spec - cursor, stdout);
+
+    switch (*++next_spec)
+    {
+    /*  All metadata fields  */
+    case 'a':
+      info.flags = METADATA_PRINTER_FLAG_NONE;
+
+iterate_meta:
+      info.counter = 0;
+      GNUNET_CONTAINER_meta_data_iterate (metadata, &item_printer, &info);
+      break;
+    /*  File's name  */
+    case 'f':
+      if (GNUNET_YES == is_directory)
+      {
+        printf ("%s%s", filename, GNUNET_FS_DIRECTORY_EXT);
+        break;
+      }
+      printf ("%s", filename);
+      break;
+    /*  Only the first metadata field  */
+    case 'j':
+      info.flags = METADATA_PRINTER_FLAG_ONE_RUN;
+      goto iterate_meta;
+    /*  File name's length  */
+    case 'l':
+      printf ("%lu",
+              (long unsigned int) (  GNUNET_YES == is_directory ?
+                                       strlen(filename) +
+                                       (sizeof(GNUNET_FS_DIRECTORY_EXT) - 1)
+                                   :
+                                       strlen(filename)));
+      break;
+    /*  File's mime type  */
+    case 'm':
+      if (GNUNET_YES == is_directory)
+      {
+        printf ("%s", GNUNET_FS_DIRECTORY_MIME);
+        break;
+      }
+      placeholder = GNUNET_CONTAINER_meta_data_get_by_type (
+        metadata,
+        EXTRACTOR_METATYPE_MIMETYPE);
+      printf ("%s", placeholder ? placeholder : GENERIC_FILE_MIMETYPE);
+      GNUNET_free (placeholder);
+      break;
+    /*  Result number  */
+    case 'n': printf ("%u", resultnum); break;
+    /*  File's size  */
+    case 's':
+      printf ("%" PRIu64, GNUNET_FS_uri_chk_get_file_size (uri));
+      break;
+    /*  File's URI  */
+    case 'u':
+      placeholder = GNUNET_FS_uri_to_string (uri);
+      printf ("%s", placeholder);
+      GNUNET_free (placeholder);
+      break;
+
+    /*  We can add as many cases as we want here...  */
+
+    /*  Handle `%123#a` and `%123#j` (e.g. `%5#j` is a book title)  */
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      cursor = next_spec;
+      info.type = *cursor - 48;
+      while (isdigit(*++cursor) && info.type < (INT_MAX - *cursor + 48) / 10)
+        info.type = info.type * 10 + *cursor - 48;
+      if (info.type == 0 || *cursor != '#')
+        goto not_a_specifier;
+      switch (*++cursor)
+      {
+      /*  All metadata fields of type `info.type`   */
+      case 'a':
+        next_spec = cursor;
+        info.flags = METADATA_PRINTER_FLAG_HAVE_TYPE;
+        goto iterate_meta;
+
+      /*  Only the first metadata field of type `info.type`  */
+      case 'j':
+        next_spec = cursor;
+        info.flags = METADATA_PRINTER_FLAG_HAVE_TYPE |
+                     METADATA_PRINTER_FLAG_ONE_RUN;
+        goto iterate_meta;
+      }
+      goto not_a_specifier;
+
+    /*  All other cases  */
+    case '%': putchar('%'); break;
+    case '\0': putchar('%'); return;
+
+not_a_specifier:
+    default: printf ("%%%c", *next_spec); break;
+    }
+    cursor = next_spec + 1;
+    next_spec = strchr(cursor, '%');
+    goto parse_format;
+  }
+
+  if (*cursor)
+    printf ("%s", cursor);
 }
 
 
 static void
-clean_task (void *cls)
+clean_task (void *const cls)
 {
   size_t dsize;
   void *ddata;
@@ -126,9 +437,10 @@ clean_task (void *cls)
                             GNUNET_DISK_PERM_USER_READ
                             | GNUNET_DISK_PERM_USER_WRITE))
   {
-    fprintf (stderr,
-             _ ("Failed to write directory with search results to `%s'\n"),
-             output_filename);
+    GNUNET_SEARCH_log(GNUNET_ERROR_TYPE_ERROR,
+                      _ ("Failed to write directory with search results to "
+                         "`%s'\n"),
+                      output_filename);
   }
   GNUNET_free (ddata);
   GNUNET_free (output_filename);
@@ -149,11 +461,11 @@ clean_task (void *cls)
  *         field in the GNUNET_FS_ProgressInfo struct.
  */
 static void *
-progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
+progress_cb (void *const cls,
+             const struct GNUNET_FS_ProgressInfo *const info)
 {
   static unsigned int cnt;
   int is_directory;
-  char *uri;
   char *filename;
 
   switch (info->status)
@@ -162,13 +474,17 @@ progress_cb (void *cls, const struct 
GNUNET_FS_ProgressInfo *info)
     break;
 
   case GNUNET_FS_STATUS_SEARCH_RESULT:
+    if (silent_mode)
+      break;
+
     if (db != NULL)
-      GNUNET_FS_directory_builder_add (db,
-                                       info->value.search.specifics.result.uri,
-                                       
info->value.search.specifics.result.meta,
-                                       NULL);
-    uri = GNUNET_FS_uri_to_string (info->value.search.specifics.result.uri);
-    printf ("#%u:\n", ++cnt);
+      GNUNET_FS_directory_builder_add (
+        db,
+        info->value.search.specifics.result.uri,
+        info->value.search.specifics.result.meta,
+        NULL);
+
+    cnt++;
     filename = GNUNET_CONTAINER_meta_data_get_by_type (
       info->value.search.specifics.result.meta,
       EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME);
@@ -179,45 +495,37 @@ progress_cb (void *cls, const struct 
GNUNET_FS_ProgressInfo *info)
       while ((filename[0] != '\0') && ('/' == filename[strlen (filename) - 1]))
         filename[strlen (filename) - 1] = '\0';
       GNUNET_DISK_filename_canonicalize (filename);
-      if (GNUNET_YES == is_directory)
-        printf ("gnunet-download -o \"%s%s\" -R %s\n",
-                filename,
-                GNUNET_FS_DIRECTORY_EXT,
-                uri);
-      else
-        printf ("gnunet-download -o \"%s\" %s\n", filename, uri);
     }
-    else if (GNUNET_YES == is_directory)
-      printf ("gnunet-download -o \"collection%s\" -R %s\n",
-              GNUNET_FS_DIRECTORY_EXT,
-              uri);
-    else
-      printf ("gnunet-download %s\n", uri);
-    if (verbose)
-      GNUNET_CONTAINER_meta_data_iterate (info->value.search.specifics.result
-                                          .meta,
-                                          &item_printer,
-                                          NULL);
-    printf ("\n");
+    print_search_result (  filename ?
+                             filename
+                         : is_directory ?
+                             GENERIC_DIRECTORY_NAME
+                         :
+                             GENERIC_FILE_NAME,
+                         info->value.search.specifics.result.uri,
+                         info->value.search.specifics.result.meta,
+                         cnt,
+                         is_directory);
     fflush (stdout);
     GNUNET_free (filename);
-    GNUNET_free (uri);
     results++;
     if ((results_limit > 0) && (results >= results_limit))
+    {
       GNUNET_SCHEDULER_shutdown ();
+      /*  otherwise the function might keep printing results for a while...  */
+      silent_mode = GNUNET_YES;
+    }
     break;
 
   case GNUNET_FS_STATUS_SEARCH_UPDATE:
-    break;
-
   case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
     /* ignore */
     break;
 
   case GNUNET_FS_STATUS_SEARCH_ERROR:
-    fprintf (stderr,
-             _ ("Error searching: %s.\n"),
-             info->value.search.specifics.error.message);
+    GNUNET_SEARCH_log(GNUNET_ERROR_TYPE_ERROR,
+                      _ ("Error searching: %s.\n"),
+                      info->value.search.specifics.error.message);
     GNUNET_SCHEDULER_shutdown ();
     break;
 
@@ -226,7 +534,9 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo 
*info)
     break;
 
   default:
-    fprintf (stderr, _ ("Unexpected status: %d\n"), info->status);
+    GNUNET_SEARCH_log(GNUNET_ERROR_TYPE_ERROR,
+                      _ ("Unexpected status: %d\n"),
+                      info->status);
     break;
   }
   return NULL;
@@ -234,7 +544,7 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo 
*info)
 
 
 static void
-shutdown_task (void *cls)
+shutdown_task (void *const cls)
 {
   if (sc != NULL)
   {
@@ -245,9 +555,10 @@ shutdown_task (void *cls)
 
 
 static void
-timeout_task (void *cls)
+timeout_task (void *const cls)
 {
   tt = NULL;
+  silent_mode = GNUNET_YES;
   GNUNET_SCHEDULER_shutdown ();
 }
 
@@ -258,18 +569,47 @@ timeout_task (void *cls)
  * @param cls closure
  * @param args remaining command-line arguments
  * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
- * @param c configuration
+ * @param cfgarg configuration
  */
 static void
-run (void *cls,
-     char *const *args,
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
+run (void *const cls,
+     char *const *const args,
+     const char *const cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *const cfgarg)
 {
   struct GNUNET_FS_Uri *uri;
   unsigned int argc;
   enum GNUNET_FS_SearchOptions options;
 
+  if (silent_mode && bookmark_only)
+  {
+    fprintf (stderr,
+             _ ("Conflicting options --bookmark-only and --silent.\n"));
+    ret = 1;
+    return;
+  }
+  if (bookmark_only && output_filename)
+  {
+    fprintf (stderr,
+             _ ("Conflicting options --bookmark-only and --output.\n"));
+    ret = 1;
+    return;
+  }
+  if (silent_mode && !output_filename)
+  {
+    fprintf (stderr, _ ("An output file is mandatory for silent mode.\n"));
+    ret = 1;
+    return;
+  }
+  if (NULL == dir_format_string)
+    dir_format_string = format_string ? format_string
+                      : verbose ? VERB_DEFAULT_DIR_FORMAT
+                      : DEFAULT_DIR_FORMAT;
+  if (NULL == format_string)
+    format_string = verbose ? VERB_DEFAULT_FILE_FORMAT
+                  : DEFAULT_FILE_FORMAT;
+  if (NULL == meta_format_string)
+    meta_format_string = DEFAULT_META_FORMAT;
   argc = 0;
   while (NULL != args[argc])
     argc++;
@@ -282,7 +622,27 @@ run (void *cls,
     ret = 1;
     return;
   }
-  cfg = c;
+  if (!GNUNET_FS_uri_test_ksk (uri) && !GNUNET_FS_uri_test_sks (uri))
+  {
+    fprintf (stderr,
+             "%s",
+             _ ("Invalid URI. Valid URIs for searching are keyword query "
+                "URIs\n(\"gnunet://fs/ksk/...\") and namespace content URIs "
+                "(\"gnunet://fs/sks/...\").\n"));
+    GNUNET_FS_uri_destroy (uri);
+    ret = 1;
+    return;
+  }
+  if (bookmark_only)
+  {
+    char * bmstr = GNUNET_FS_uri_to_string (uri);
+    printf ("%s\n", bmstr);
+    GNUNET_free (bmstr);
+    GNUNET_FS_uri_destroy (uri);
+    ret = 0;
+    return;
+  }
+  cfg = cfgarg;
   ctx = GNUNET_FS_start (cfg,
                          "gnunet-search",
                          &progress_cb,
@@ -291,7 +651,7 @@ run (void *cls,
                          GNUNET_FS_OPTIONS_END);
   if (NULL == ctx)
   {
-    fprintf (stderr, _ ("Could not initialize `%s' subsystem.\n"), "FS");
+    fprintf (stderr, _ ("Could not initialize the `%s` subsystem.\n"), "FS");
     GNUNET_FS_uri_destroy (uri);
     ret = 1;
     return;
@@ -321,18 +681,74 @@ run (void *cls,
  *
  * @param argc number of arguments from the command line
  * @param argv command line arguments
- * @return 0 ok, 1 on error
+ * @return 0 ok, an error number on error
  */
 int
 main (int argc, char *const *argv)
 {
   struct GNUNET_GETOPT_CommandLineOption options[] =
-  { GNUNET_GETOPT_option_uint ('a',
-                               "anonymity",
-                               "LEVEL",
-                               gettext_noop (
-                                 "set the desired LEVEL of 
receiver-anonymity"),
-                               &anonymity),
+  { GNUNET_GETOPT_option_uint (
+      'a',
+      "anonymity",
+      "LEVEL",
+      gettext_noop ("set the desired LEVEL of receiver-anonymity (default: "
+                    "1)"),
+      &anonymity),
+    GNUNET_GETOPT_option_flag (
+      'b',
+      "bookmark-only",
+      gettext_noop ("do not search, print only the URI that points to this "
+                    "search"),
+      &bookmark_only),
+    GNUNET_GETOPT_option_string (
+      'F',
+      "dir-printf",
+      "FORMAT",
+      gettext_noop ("write search results for directories according to "
+                    "FORMAT; the format specifiers supported here are "
+                    "identical to those supported in the --printf argument "
+                    "(please refer to it for more information); if missing, "
+                    "--dir-printf defaults to --printf; if --printf is "
+                    "missing too --dir-printf defaults to `"
+                    HELP_DEFAULT_DIR_FORMAT "`"),
+      &dir_format_string),
+    GNUNET_GETOPT_option_string (
+      'f',
+      "printf",
+      "FORMAT",
+      gettext_noop ("write search results according to FORMAT, where %a is "
+                    "the complete list of all the printable metadata "
+                    "available (each member will be displayed according to "
+                    "the --iter-printf argument) - use %j for printing only "
+                    "one field - %f is the file's name, %l is the file name's "
+                    "length, %m is the file's mime type, %n is the search "
+                    "result number, %s is the file's size in bytes and %u is "
+                    "the file's URI; the %a and %j specifiers optionally "
+                    "support metatype filtering via hash sign (e.g. `%5#j` "
+                    "prints a book title, if present - see libextractor's "
+                    "metatypes for the complete list of numerical "
+                    "identifiers); if missing, --printf defaults to `"
+                    HELP_DEFAULT_FILE_FORMAT "`"),
+      &format_string),
+    GNUNET_GETOPT_option_string (
+      'i',
+      "iter-printf",
+      "FORMAT",
+      gettext_noop ("when the %a or %j format specifiers appear in --printf "
+                    "or --dir-printf, list each metadata property according "
+                    "to FORMAT, where %p is the property's content, %l is the "
+                    "content's length in bytes" HELP_EXTRACTOR_TEXTADD ", %i "
+                    "is the property type's unique identifier, %n is the "
+                    "property number and %w is the name of the plugin that "
+                    "provided the information; if missing, --iter-printf "
+                    "defaults to `" HELP_DEFAULT_META_FORMAT "`"),
+      &meta_format_string),
+    GNUNET_GETOPT_option_uint ('N',
+                               "results",
+                               "VALUE",
+                               gettext_noop ("automatically terminate search "
+                                             "after VALUE results are found"),
+                               &results_limit),
     GNUNET_GETOPT_option_flag (
       'n',
       "no-network",
@@ -341,39 +757,55 @@ main (int argc, char *const *argv)
     GNUNET_GETOPT_option_string (
       'o',
       "output",
-      "PREFIX",
-      gettext_noop ("write search results to file starting with PREFIX"),
+      "FILENAME",
+      gettext_noop ("create a GNUnet directory with search results at "
+                    "FILENAME (e.g. `gnunet-search --output=commons"
+                    GNUNET_FS_DIRECTORY_EXT " commons`)"),
       &output_filename),
+    GNUNET_GETOPT_option_flag (
+      's',
+      "silent",
+      gettext_noop ("silent mode (requires the --output argument)"),
+      &silent_mode),
     GNUNET_GETOPT_option_relative_time (
       't',
       "timeout",
       "DELAY",
-      gettext_noop ("automatically terminate search after DELAY"),
+      gettext_noop ("automatically terminate search after DELAY (in number of "
+                    "microseconds - 1 second = 1000000); if 0 or omitted it "
+                    "means to wait for CTRL-C"),
       &timeout),
-    GNUNET_GETOPT_option_verbose (&verbose),
-    GNUNET_GETOPT_option_uint ('N',
-                               "results",
-                               "VALUE",
-                               gettext_noop ("automatically terminate search "
-                                             "after VALUE results are found"),
-                               &results_limit),
+    GNUNET_GETOPT_option_increment_uint (
+      'V',
+      "verbose",
+      gettext_noop ("be verbose (append \"%a\\n\" to the default --printf and "
+                    "--dir-printf arguments - ignored when these are provided "
+                    "by the user)"),
+      &verbose),
     GNUNET_GETOPT_OPTION_END };
 
   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
     return 2;
 
-  ret =
-    (GNUNET_OK ==
-     GNUNET_PROGRAM_run (argc,
-                         argv,
-                         "gnunet-search [OPTIONS] KEYWORD",
-                         gettext_noop (
-                           "Search GNUnet for files that were published on 
GNUnet"),
+  if (GNUNET_SYSERR == 
+      GNUNET_PROGRAM_run (argc,
+                          argv,
+                          "gnunet-search [OPTIONS] KEYWORD1 KEYWORD2 ...",
+                          gettext_noop ("Search for files that have been "
+                                        "published on GNUnet\n\nKeywords "
+                                        "should start with a plus sign to "
+                                        "indicate that they are required -\n"
+                                        "e.g. `gnunet-search commons gpl` "
+                                        "searches for files that match "
+                                        "*either*\n\"commons\" or \"gpl\", "
+                                        "whereas `gnunet-search +commons "
+                                        "+gpl` searches for files\nthat match "
+                                        "*both* \"commons\" and \"gpl\".\n"),
                          options,
                          &run,
                          NULL))
-    ? ret
-    : 1;
+    ret = 1;
+
   GNUNET_free_nz ((void *) argv);
   return ret;
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]