- Allocate buffer large enough to contain UNIX_PATH_MAX size pathnames in case of...
[oweals/gnunet.git] / src / util / getopt_helpers.c
1 /*
2      This file is part of GNUnet
3      (C) 2006, 2011 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file src/util/getopt_helpers.c
23  * @brief implements command line that sets option
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28
29 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
30
31
32 /**
33  * Print out program version (implements --version).
34  *
35  * @param ctx command line processing context
36  * @param scls additional closure (points to version string)
37  * @param option name of the option
38  * @param value not used (NULL)
39  * @return GNUNET_NO (do not continue, not an error)
40  */
41 int
42 GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext
43                               *ctx, void *scls, const char *option,
44                               const char *value)
45 {
46   const char *version = scls;
47
48   printf ("%s v%s\n", ctx->binaryName, version);
49   return GNUNET_NO;
50 }
51
52
53
54 #define BORDER 29
55
56 /**
57  * Print out details on command line options (implements --help).
58  *
59  * @param ctx command line processing context
60  * @param scls additional closure (points to about text)
61  * @param option name of the option
62  * @param value not used (NULL)
63  * @return GNUNET_NO (do not continue, not an error)
64  */
65 int
66 GNUNET_GETOPT_format_help_ (struct GNUNET_GETOPT_CommandLineProcessorContext
67                             *ctx, void *scls, const char *option,
68                             const char *value)
69 {
70   const char *about = scls;
71   size_t slen;
72   unsigned int i;
73   int j;
74   size_t ml;
75   size_t p;
76   char *scp;
77   const char *trans;
78   const struct GNUNET_GETOPT_CommandLineOption *opt;
79
80   if (NULL != about)
81   {
82     printf ("%s\n%s\n", ctx->binaryOptions, gettext (about));
83     printf (_
84             ("Arguments mandatory for long options are also mandatory for short options.\n"));
85   }
86   i = 0;
87   opt = ctx->allOptions;
88   while (opt[i].description != NULL)
89   {
90     if (opt[i].shortName == '\0')
91       printf ("      ");
92     else
93       printf ("  -%c, ", opt[i].shortName);
94     printf ("--%s", opt[i].name);
95     slen = 8 + strlen (opt[i].name);
96     if (opt[i].argumentHelp != NULL)
97     {
98       printf ("=%s", opt[i].argumentHelp);
99       slen += 1 + strlen (opt[i].argumentHelp);
100     }
101     if (slen > BORDER)
102     {
103       printf ("\n%*s", BORDER, "");
104       slen = BORDER;
105     }
106     if (slen < BORDER)
107     {
108       printf ("%*s", (int) (BORDER - slen), "");
109       slen = BORDER;
110     }
111     if (0 < strlen (opt[i].description))
112       trans = gettext (opt[i].description);
113     else
114       trans = "";
115     ml = strlen (trans);
116     p = 0;
117 OUTER:
118     while (ml - p > 78 - slen)
119     {
120       for (j = p + 78 - slen; j > p; j--)
121       {
122         if (isspace ((unsigned char) trans[j]))
123         {
124           scp = GNUNET_malloc (j - p + 1);
125           memcpy (scp, &trans[p], j - p);
126           scp[j - p] = '\0';
127           printf ("%s\n%*s", scp, BORDER + 2, "");
128           GNUNET_free (scp);
129           p = j + 1;
130           slen = BORDER + 2;
131           goto OUTER;
132         }
133       }
134       /* could not find space to break line */
135       scp = GNUNET_malloc (78 - slen + 1);
136       memcpy (scp, &trans[p], 78 - slen);
137       scp[78 - slen] = '\0';
138       printf ("%s\n%*s", scp, BORDER + 2, "");
139       GNUNET_free (scp);
140       slen = BORDER + 2;
141       p = p + 78 - slen;
142     }
143     /* print rest */
144     if (p < ml)
145       printf ("%s\n", &trans[p]);
146     if (strlen (trans) == 0)
147       printf ("\n");
148     i++;
149   }
150   printf ("Report bugs to gnunet-developers@gnu.org.\n"
151           "GNUnet home page: http://www.gnu.org/software/gnunet/\n"
152           "General help using GNU software: http://www.gnu.org/gethelp/\n");
153   return GNUNET_NO;
154 }
155
156
157 /**
158  * Set an option of type 'unsigned int' from the command line. Each
159  * time the option flag is given, the value is incremented by one.
160  * A pointer to this function should be passed as part of the
161  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
162  * of this type.  It should be followed by a pointer to a value of
163  * type 'int'.
164  *
165  * @param ctx command line processing context
166  * @param scls additional closure (will point to the 'int')
167  * @param option name of the option
168  * @param value not used (NULL)
169  * @return GNUNET_OK
170  */
171 int
172 GNUNET_GETOPT_increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext
173                                *ctx, void *scls, const char *option,
174                                const char *value)
175 {
176   int *val = scls;
177
178   (*val)++;
179   return GNUNET_OK;
180 }
181
182
183 /**
184  * Set an option of type 'int' from the command line to 1 if the
185  * given option is present.
186  * A pointer to this function should be passed as part of the
187  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
188  * of this type.  It should be followed by a pointer to a value of
189  * type 'int'.
190  *
191  * @param ctx command line processing context
192  * @param scls additional closure (will point to the 'int')
193  * @param option name of the option
194  * @param value not used (NULL)
195  * @return GNUNET_OK
196  */
197 int
198 GNUNET_GETOPT_set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
199                        void *scls, const char *option, const char *value)
200 {
201   int *val = scls;
202
203   *val = 1;
204   return GNUNET_OK;
205 }
206
207
208 /**
209  * Set an option of type 'char *' from the command line.
210  * A pointer to this function should be passed as part of the
211  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
212  * of this type.  It should be followed by a pointer to a value of
213  * type 'char *', which will be allocated with the requested string.
214  *
215  * @param ctx command line processing context
216  * @param scls additional closure (will point to the 'char *',
217  *             which will be allocated)
218  * @param option name of the option
219  * @param value actual value of the option (a string)
220  * @return GNUNET_OK
221  */
222 int
223 GNUNET_GETOPT_set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
224                           void *scls, const char *option, const char *value)
225 {
226   char **val = scls;
227
228   GNUNET_assert (value != NULL);
229   GNUNET_free_non_null (*val);
230   *val = GNUNET_strdup (value);
231   return GNUNET_OK;
232 }
233
234
235 int
236 GNUNET_GETOPT_set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
237                             void *scls, const char *option, const char *value)
238 {
239   char **val = scls;
240
241   GNUNET_assert (value != NULL);
242   GNUNET_free_non_null (*val);
243   *val = GNUNET_STRINGS_filename_expand (value);
244   return GNUNET_OK;
245 }
246
247 /**
248  * Set an option of type 'unsigned long long' from the command line.
249  * A pointer to this function should be passed as part of the
250  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
251  * of this type.  It should be followed by a pointer to a value of
252  * type 'unsigned long long'.
253  *
254  * @param ctx command line processing context
255  * @param scls additional closure (will point to the 'unsigned long long')
256  * @param option name of the option
257  * @param value actual value of the option as a string.
258  * @return GNUNET_OK if parsing the value worked
259  */
260 int
261 GNUNET_GETOPT_set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
262                          void *scls, const char *option, const char *value)
263 {
264   unsigned long long *val = scls;
265
266   if (1 != SSCANF (value, "%llu", val))
267   {
268     FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), option);
269     return GNUNET_SYSERR;
270   }
271   return GNUNET_OK;
272 }
273
274
275 /**
276  * Set an option of type 'struct GNUNET_TIME_Relative' from the command line.
277  * A pointer to this function should be passed as part of the
278  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
279  * of this type.  It should be followed by a pointer to a value of
280  * type 'struct GNUNET_TIME_Relative'.
281  *
282  * @param ctx command line processing context
283  * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative')
284  * @param option name of the option
285  * @param value actual value of the option as a string.
286  * @return GNUNET_OK if parsing the value worked
287  */
288 int
289 GNUNET_GETOPT_set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
290                                  void *scls, const char *option, const char *value)
291 {
292   struct GNUNET_TIME_Relative *val = scls;
293
294   if (GNUNET_OK !=
295       GNUNET_STRINGS_fancy_time_to_relative (value,
296                                              val))
297   {
298     FPRINTF (stderr, _("You must pass relative time to the `%s' option.\n"), option);
299     return GNUNET_SYSERR;
300   }
301   return GNUNET_OK;
302 }
303
304
305 /**
306  * Set an option of type 'unsigned int' from the command line.
307  * A pointer to this function should be passed as part of the
308  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
309  * of this type.  It should be followed by a pointer to a value of
310  * type 'unsigned int'.
311  *
312  * @param ctx command line processing context
313  * @param scls additional closure (will point to the 'unsigned int')
314  * @param option name of the option
315  * @param value actual value of the option as a string.
316  * @return GNUNET_OK if parsing the value worked
317  */
318 int
319 GNUNET_GETOPT_set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
320                         void *scls, const char *option, const char *value)
321 {
322   unsigned int *val = scls;
323
324   if (1 != SSCANF (value, "%u", val))
325   {
326     FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), option);
327     return GNUNET_SYSERR;
328   }
329   return GNUNET_OK;
330 }
331
332
333 /* end of getopt_helpers.c */