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