reduce loop counters to more practical levels
[oweals/gnunet.git] / src / fs / fs_getopt.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file fs/fs_getopt.c
23  * @brief helper functions for command-line argument processing
24  * @author Igor Wronsky, Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_fs_service.h"
28 #include "gnunet_getopt_lib.h"
29 #include "fs_api.h"
30
31 /* ******************** command-line option parsing API ******************** */
32
33 /**
34  * Command-line option parser function that allows the user
35  * to specify one or more '-k' options with keywords.  Each
36  * specified keyword will be added to the URI.  A pointer to
37  * the URI must be passed as the "scls" argument.
38  *
39  * @param ctx command line processor context
40  * @param scls must be of type "struct GNUNET_FS_Uri **"
41  * @param option name of the option (typically 'k')
42  * @param value command line argument given
43  * @return GNUNET_OK on success
44  */
45 static int
46 getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext
47                      *ctx, void *scls, const char *option,
48                       const char *value)
49 {
50   struct GNUNET_FS_Uri **uri = scls;
51   struct GNUNET_FS_Uri *u = *uri;
52   char *val;
53   size_t slen;
54
55   if (u == NULL)
56   {
57     u = GNUNET_new (struct GNUNET_FS_Uri);
58     *uri = u;
59     u->type = GNUNET_FS_URI_KSK;
60     u->data.ksk.keywordCount = 0;
61     u->data.ksk.keywords = NULL;
62   }
63   else
64   {
65     GNUNET_assert (u->type == GNUNET_FS_URI_KSK);
66   }
67   slen = strlen (value);
68   if (slen == 0)
69     return GNUNET_SYSERR;       /* cannot be empty */
70   if (value[0] == '+')
71   {
72     /* simply preserve the "mandatory" flag */
73     if (slen < 2)
74       return GNUNET_SYSERR;     /* empty keywords not allowed */
75     if ((value[1] == '"') && (slen > 3) && (value[slen - 1] == '"'))
76     {
77       /* remove the quotes, keep the '+' */
78       val = GNUNET_malloc (slen - 1);
79       val[0] = '+';
80       GNUNET_memcpy (&val[1], &value[2], slen - 3);
81       val[slen - 2] = '\0';
82     }
83     else
84     {
85       /* no quotes, just keep the '+' */
86       val = GNUNET_strdup (value);
87     }
88   }
89   else
90   {
91     if ((value[0] == '"') && (slen > 2) && (value[slen - 1] == '"'))
92     {
93       /* remove the quotes, add a space */
94       val = GNUNET_malloc (slen);
95       val[0] = ' ';
96       GNUNET_memcpy (&val[1], &value[1], slen - 2);
97       val[slen - 1] = '\0';
98     }
99     else
100     {
101       /* add a space to indicate "not mandatory" */
102       val = GNUNET_malloc (slen + 2);
103       strcpy (val, " ");
104       strcat (val, value);
105     }
106   }
107   GNUNET_array_append (u->data.ksk.keywords, u->data.ksk.keywordCount, val);
108   return GNUNET_OK;
109 }
110
111 /**
112  * Allow user to specify keywords.
113  *
114  * @param shortName short name of the option
115  * @param name long name of the option
116  * @param argumentHelp help text for the option argument
117  * @param description long help text for the option
118  * @param[out] topKeywords set to the desired value
119  */
120 struct GNUNET_GETOPT_CommandLineOption
121 GNUNET_FS_GETOPT_KEYWORDS (char shortName,
122                            const char *name,
123                            const char *argumentHelp,
124                            const char *description,
125                            struct GNUNET_FS_Uri **topKeywords)
126 {
127   struct GNUNET_GETOPT_CommandLineOption clo = {
128     .shortName = shortName,
129     .name = name,
130     .argumentHelp = argumentHelp,
131     .description = description,
132     .require_argument = 1,
133     .processor = &getopt_set_keywords,
134     .scls = (void *) topKeywords  
135   };
136
137   return clo;
138 }
139
140 /**
141  * Command-line option parser function that allows the user to specify
142  * one or more '-m' options with metadata.  Each specified entry of
143  * the form "type=value" will be added to the metadata.  A pointer to
144  * the metadata must be passed as the "scls" argument.
145  *
146  * @param ctx command line processor context
147  * @param scls must be of type "struct GNUNET_MetaData **"
148  * @param option name of the option (typically 'k')
149  * @param value command line argument given
150  * @return #GNUNET_OK on success
151  */
152 static int
153 getopt_set_metadata (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
154                      void *scls,
155                      const char *option,
156                      const char *value)
157 {
158   struct GNUNET_CONTAINER_MetaData **mm = scls;
159 #if HAVE_EXTRACTOR_H && HAVE_LIBEXTRACTOR
160   enum EXTRACTOR_MetaType type;
161   const char *typename;
162   const char *typename_i18n;
163 #endif
164   struct GNUNET_CONTAINER_MetaData *meta;
165   char *tmp;
166
167   meta = *mm;
168   if (meta == NULL)
169   {
170     meta = GNUNET_CONTAINER_meta_data_create ();
171     *mm = meta;
172   }
173
174   /* Use GNUNET_STRINGS_get_utf8_args() in main() to acquire utf-8-encoded
175    * commandline arguments, so that the following line is not needed.
176    */
177   /*tmp = GNUNET_STRINGS_to_utf8 (value, strlen (value), locale_charset ());*/
178   tmp = GNUNET_strdup (value);
179 #if HAVE_EXTRACTOR_H && HAVE_LIBEXTRACTOR
180   type = EXTRACTOR_metatype_get_max ();
181   while (type > 0)
182   {
183     type--;
184     typename = EXTRACTOR_metatype_to_string (type);
185     typename_i18n = dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN, typename);
186     if ((strlen (tmp) >= strlen (typename) + 1) &&
187         (tmp[strlen (typename)] == ':') &&
188         (0 == strncmp (typename, tmp, strlen (typename))))
189     {
190       GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", type,
191                                          EXTRACTOR_METAFORMAT_UTF8,
192                                          "text/plain",
193                                          &tmp[strlen (typename) + 1],
194                                          strlen (&tmp[strlen (typename) + 1]) +
195                                          1);
196       GNUNET_free (tmp);
197       tmp = NULL;
198       break;
199     }
200     if ((strlen (tmp) >= strlen (typename_i18n) + 1) &&
201         (tmp[strlen (typename_i18n)] == ':') &&
202         (0 == strncmp (typename_i18n, tmp, strlen (typename_i18n))))
203     {
204       GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", type,
205                                          EXTRACTOR_METAFORMAT_UTF8,
206                                          "text/plain",
207                                          &tmp[strlen (typename_i18n) + 1],
208                                          strlen (&tmp
209                                                  [strlen (typename_i18n) + 1]) +
210                                          1);
211       GNUNET_free (tmp);
212       tmp = NULL;
213       break;
214     }
215   }
216 #endif
217
218   if (NULL != tmp)
219   {
220     GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>",
221                                        EXTRACTOR_METATYPE_UNKNOWN,
222                                        EXTRACTOR_METAFORMAT_UTF8, "text/plain",
223                                        tmp, strlen (tmp) + 1);
224     GNUNET_free (tmp);
225     printf (_
226             ("Unknown metadata type in metadata option `%s'.  Using metadata type `unknown' instead.\n"),
227             value);
228   }
229   return GNUNET_OK;
230 }
231
232 /**
233  * Allow user to specify metadata.
234  *
235  * @param shortName short name of the option
236  * @param name long name of the option
237  * @param argumentHelp help text for the option argument
238  * @param description long help text for the option
239  * @param[out] metadata set to the desired value
240  */
241 struct GNUNET_GETOPT_CommandLineOption
242 GNUNET_FS_GETOPT_METADATA (char shortName,
243                            const char *name,
244                            const char *argumentHelp,
245                            const char *description,
246                            struct GNUNET_CONTAINER_MetaData **meta)
247 {
248   struct GNUNET_GETOPT_CommandLineOption clo = {
249     .shortName = shortName,
250     .name = name,
251     .argumentHelp = argumentHelp,
252     .description = description,
253     .require_argument = 1,
254     .processor = &getopt_set_metadata,
255     .scls = (void *) meta
256   };
257
258   return clo;
259 }
260
261
262
263
264 /* end of fs_getopt.c */