first batch of license fixes (boring)
[oweals/gnunet.git] / src / identity / gnunet-identity.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14 */
15 /**
16  * @file identity/gnunet-identity.c
17  * @brief IDENTITY management command line tool
18  * @author Christian Grothoff
19  *
20  * Todo:
21  * - add options to get default egos
22  */
23 #include "platform.h"
24 #include "gnunet_util_lib.h"
25 #include "gnunet_identity_service.h"
26
27
28 /**
29  * Return value from main on timeout.
30  */
31 #define TIMEOUT_STATUS_CODE 40
32
33 /**
34  * Handle to IDENTITY service.
35  */
36 static struct GNUNET_IDENTITY_Handle *sh;
37
38 /**
39  * Was "list" specified?
40  */
41 static int list;
42
43 /**
44  * Was "monitor" specified?
45  */
46 static int monitor;
47
48 /**
49  * -C option
50  */
51 static char *create_ego;
52
53 /**
54  * -D option
55  */
56 static char *delete_ego;
57
58 /**
59  * -s option.
60  */
61 static char *set_ego;
62
63 /**
64  * -S option.
65  */
66 static char *set_subsystem;
67
68 /**
69  * Operation handle for set operation.
70  */
71 static struct GNUNET_IDENTITY_Operation *set_op;
72
73 /**
74  * Handle for create operation.
75  */
76 static struct GNUNET_IDENTITY_Operation *create_op;
77
78 /**
79  * Handle for delete operation.
80  */
81 static struct GNUNET_IDENTITY_Operation *delete_op;
82
83 /**
84  * Value to return from #main().
85  */
86 static int global_ret;
87
88
89 /**
90  * Task run on shutdown.
91  *
92  * @param cls NULL
93  */
94 static void
95 shutdown_task (void *cls)
96 {
97   if (NULL != set_op)
98   {
99     GNUNET_IDENTITY_cancel (set_op);
100     set_op = NULL;
101   }
102   if (NULL != create_op)
103   {
104     GNUNET_IDENTITY_cancel (create_op);
105     create_op = NULL;
106   }
107   if (NULL != delete_op)
108   {
109     GNUNET_IDENTITY_cancel (delete_op);
110     delete_op = NULL;
111   }
112   GNUNET_IDENTITY_disconnect (sh);
113   sh = NULL;
114 }
115
116
117 /**
118  * Test if we are finished yet.
119  */
120 static void
121 test_finished ()
122 {
123   if ( (NULL == create_op) &&
124        (NULL == delete_op) &&
125        (NULL == set_op) &&
126        (NULL == set_ego) &&
127        (! list) &&
128        (! monitor) )
129   {
130     if (TIMEOUT_STATUS_CODE == global_ret)
131       global_ret = 0;
132     GNUNET_SCHEDULER_shutdown ();
133   }
134 }
135
136
137 /**
138  * Deletion operation finished.
139  *
140  * @param cls pointer to operation handle
141  * @param emsg NULL on success, otherwise an error message
142  */
143 static void
144 delete_finished (void *cls,
145                  const char *emsg)
146 {
147   struct GNUNET_IDENTITY_Operation **op = cls;
148
149   *op = NULL;
150   if (NULL != emsg)
151     fprintf (stderr,
152              "%s\n",
153              gettext (emsg));
154   test_finished ();
155 }
156
157
158 /**
159  * Creation operation finished.
160  *
161  * @param cls pointer to operation handle
162  * @param emsg error message, NULL on success
163  */
164 static void
165 create_finished (void *cls,
166                  const char *emsg)
167 {
168   struct GNUNET_IDENTITY_Operation **op = cls;
169
170   *op = NULL;
171   if (NULL != emsg)
172   {
173     fprintf (stderr,
174              _("Failed to create ego: %s\n"),
175              emsg);
176     global_ret = 1;
177   }
178   test_finished ();
179 }
180
181
182 /**
183  * Function called by #GNUNET_IDENTITY_set up on completion.
184  *
185  * @param cls NULL
186  * @param emsg error message (NULL on success)
187  */
188 static void
189 set_done (void *cls,
190           const char *emsg)
191 {
192   set_op = NULL;
193   if (NULL != emsg)
194   {
195     fprintf (stderr,
196              _("Failed to set default ego: %s\n"),
197              emsg);
198     global_ret = 1;
199   }
200   test_finished ();
201 }
202
203
204 /**
205  * If listing is enabled, prints information about the egos.
206  *
207  * This function is initially called for all egos and then again
208  * whenever a ego's identifier changes or if it is deleted.  At the
209  * end of the initial pass over all egos, the function is once called
210  * with 'NULL' for 'ego'. That does NOT mean that the callback won't
211  * be invoked in the future or that there was an error.
212  *
213  * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
214  * this function is only called ONCE, and 'NULL' being passed in
215  * 'ego' does indicate an error (i.e. name is taken or no default
216  * value is known).  If 'ego' is non-NULL and if '*ctx'
217  * is set in those callbacks, the value WILL be passed to a subsequent
218  * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
219  * that one was not NULL).
220  *
221  * When an identity is renamed, this function is called with the
222  * (known) ego but the NEW identifier.
223  *
224  * When an identity is deleted, this function is called with the
225  * (known) ego and "NULL" for the 'identifier'.  In this case,
226  * the 'ego' is henceforth invalid (and the 'ctx' should also be
227  * cleaned up).
228  *
229  * @param cls closure
230  * @param ego ego handle
231  * @param ctx context for application to store data for this ego
232  *                 (during the lifetime of this process, initially NULL)
233  * @param identifier identifier assigned by the user for this ego,
234  *                   NULL if the user just deleted the ego and it
235  *                   must thus no longer be used
236 */
237 static void
238 print_ego (void *cls,
239            struct GNUNET_IDENTITY_Ego *ego,
240            void **ctx,
241            const char *identifier)
242 {
243   struct GNUNET_CRYPTO_EcdsaPublicKey pk;
244   char *s;
245
246   if ( (NULL != set_ego) &&
247        (NULL != ego) &&
248        (NULL != identifier) &&
249        (0 == strcmp (identifier,
250                      set_ego)) )
251     {
252       set_op = GNUNET_IDENTITY_set (sh,
253                                     set_subsystem,
254                                     ego,
255                                     &set_done,
256                                     NULL);
257       GNUNET_free (set_subsystem);
258       set_subsystem = NULL;
259       GNUNET_free (set_ego);
260       set_ego = NULL;
261     }
262   if ( (NULL == ego) &&
263        (NULL != set_ego) )
264   {
265     fprintf (stderr,
266              "Could not set ego to `%s' for subsystem `%s', ego not known\n",
267              set_ego,
268              set_subsystem);
269     GNUNET_free (set_subsystem);
270     set_subsystem = NULL;
271     GNUNET_free (set_ego);
272     set_ego = NULL;
273   }
274   if ( (NULL == ego) && (! monitor) )
275   {
276     list = 0;
277     test_finished ();
278     return;
279   }
280   if (! (list | monitor))
281     return;
282   if (NULL == ego)
283     return;
284   GNUNET_IDENTITY_ego_get_public_key (ego,
285                                       &pk);
286   s = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
287   if ( (monitor) ||
288        (NULL != identifier) )
289     fprintf (stdout,
290              "%s - %s\n",
291              identifier,
292              s);
293   GNUNET_free (s);
294 }
295
296
297 /**
298  * Main function that will be run by the scheduler.
299  *
300  * @param cls closure
301  * @param args remaining command-line arguments
302  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
303  * @param cfg configuration
304  */
305 static void
306 run (void *cls,
307      char *const *args,
308      const char *cfgfile,
309      const struct GNUNET_CONFIGURATION_Handle *cfg)
310 {
311   if ( (NULL == set_subsystem) ^
312        (NULL == set_ego) )
313   {
314     fprintf (stderr,
315              "Options -e and -s must always be specified together\n");
316     return;
317   }
318   sh = GNUNET_IDENTITY_connect (cfg,
319                                 &print_ego,
320                                 NULL);
321   if (NULL != delete_ego)
322     delete_op = GNUNET_IDENTITY_delete (sh,
323                                         delete_ego,
324                                         &delete_finished,
325                                         &delete_op);
326   if (NULL != create_ego)
327     create_op = GNUNET_IDENTITY_create (sh,
328                                         create_ego,
329                                         &create_finished,
330                                         &create_op);
331   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
332                                  NULL);
333   test_finished ();
334 }
335
336
337 /**
338  * The main function.
339  *
340  * @param argc number of arguments from the command line
341  * @param argv command line arguments
342  * @return 0 ok, 1 on error
343  */
344 int
345 main (int argc, char *const *argv)
346 {
347   struct GNUNET_GETOPT_CommandLineOption options[] = {
348     GNUNET_GETOPT_option_string ('C',
349                                  "create",
350                                  "NAME",
351                                  gettext_noop ("create ego NAME"),
352                                  &create_ego),
353
354     GNUNET_GETOPT_option_string ('D',
355                                  "delete",
356                                  "NAME",
357                                  gettext_noop ("delete ego NAME "),
358                                  &delete_ego),
359
360     GNUNET_GETOPT_option_flag ('d',
361                                   "display",
362                                   gettext_noop ("display all egos"),
363                                   &list),
364     
365     GNUNET_GETOPT_option_string ('e',
366                                  "ego",
367                                  "NAME",
368                                  gettext_noop ("set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)"),
369                                  &set_ego),
370
371     GNUNET_GETOPT_option_flag ('m',
372                                   "monitor",
373                                   gettext_noop ("run in monitor mode egos"),
374                                   &monitor),
375
376     GNUNET_GETOPT_option_string ('s',
377                                  "set",
378                                  "SUBSYSTEM",
379                                  gettext_noop ("set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"),
380                                  &set_subsystem),
381
382     GNUNET_GETOPT_OPTION_END
383   };
384   int res;
385
386   if (GNUNET_OK !=
387       GNUNET_STRINGS_get_utf8_args (argc, argv,
388                                     &argc, &argv))
389     return 4;
390   global_ret = TIMEOUT_STATUS_CODE; /* timeout */
391   res = GNUNET_PROGRAM_run (argc, argv,
392                             "gnunet-identity",
393                             gettext_noop ("Maintain egos"),
394                             options, &run,
395                             NULL);
396   GNUNET_free ((void *) argv);
397
398   if (GNUNET_OK != res)
399     return 3;
400   return global_ret;
401 }
402
403 /* end of gnunet-identity.c */