aboutsummaryrefslogtreecommitdiff
path: root/src/chat/gnunet-chat.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-05-29 08:19:14 +0000
committerChristian Grothoff <christian@grothoff.org>2013-05-29 08:19:14 +0000
commit1bdbb8bc0cec3650843daf5eb559ed46e9a69fd7 (patch)
tree95f01ee9c62b026c4c161a62d309f25b05acc5cc /src/chat/gnunet-chat.c
parent022002438e4047d235a688cfd9da7b63ab990103 (diff)
downloadgnunet-1bdbb8bc0cec3650843daf5eb559ed46e9a69fd7.tar.gz
gnunet-1bdbb8bc0cec3650843daf5eb559ed46e9a69fd7.zip
-removing chat from build
Diffstat (limited to 'src/chat/gnunet-chat.c')
-rw-r--r--src/chat/gnunet-chat.c750
1 files changed, 0 insertions, 750 deletions
diff --git a/src/chat/gnunet-chat.c b/src/chat/gnunet-chat.c
deleted file mode 100644
index 2d2f8f835..000000000
--- a/src/chat/gnunet-chat.c
+++ /dev/null
@@ -1,750 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2007, 2008, 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 chat/gnunet-chat.c
23 * @brief Minimal chat command line tool
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 * @author Vitaly Minko
27 */
28
29#include "platform.h"
30#include "gnunet_getopt_lib.h"
31#include "gnunet_program_lib.h"
32#include "gnunet_chat_service.h"
33#include "gnunet_fs_service.h"
34#include <fcntl.h>
35
36static int ret;
37
38static const struct GNUNET_CONFIGURATION_Handle *cfg;
39
40static char *nickname;
41
42static char *room_name;
43
44static struct GNUNET_CONTAINER_MetaData *meta;
45
46static struct GNUNET_CHAT_Room *room;
47
48static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task;
49
50typedef int (*ActionFunction)(const char *argumetns, const void *xtra);
51
52struct ChatCommand
53{
54 const char *command;
55 ActionFunction Action;
56 const char *helptext;
57};
58
59struct UserList
60{
61 struct UserList *next;
62 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
63 int ignored;
64};
65
66static struct UserList *users;
67
68static void
69free_user_list ()
70{
71 struct UserList *next;
72
73 while (NULL != users)
74 {
75 next = users->next;
76 GNUNET_free (users);
77 users = next;
78 }
79}
80
81static int
82do_help (const char *args, const void *xtra);
83
84
85/**
86 * Callback used for notification that we have joined the room.
87 *
88 * @param cls closure
89 * @return GNUNET_OK
90 */
91static int
92join_cb (void *cls)
93{
94 FPRINTF (stdout, "%s", _("Joined\n"));
95 return GNUNET_OK;
96}
97
98
99/**
100 * Callback used for notification about incoming messages.
101 *
102 * @param cls closure, NULL
103 * @param room in which room was the message received?
104 * @param sender what is the ID of the sender? (maybe NULL)
105 * @param member_info information about the joining member
106 * @param message the message text
107 * @param timestamp time when the member joined
108 * @param options options for the message
109 * @return GNUNET_OK to accept the message now, GNUNET_NO to
110 * accept (but user is away), GNUNET_SYSERR to signal denied delivery
111 */
112static int
113receive_cb (void *cls, struct GNUNET_CHAT_Room *room,
114 const struct GNUNET_HashCode * sender,
115 const struct GNUNET_CONTAINER_MetaData *member_info,
116 const char *message, struct GNUNET_TIME_Absolute timestamp,
117 enum GNUNET_CHAT_MsgOptions options)
118{
119 char *non_unique_nick;
120 char *nick;
121 int nick_is_a_dup;
122 const char *timestr;
123 const char *fmt;
124
125 if (NULL == sender)
126 nick = GNUNET_strdup (_("anonymous"));
127 else
128 {
129 if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
130 sender, NULL, NULL, &non_unique_nick, &nick_is_a_dup)
131 || (nick_is_a_dup == GNUNET_YES))
132 {
133 GNUNET_free (non_unique_nick);
134 non_unique_nick = GNUNET_strdup (_("anonymous"));
135 }
136 nick = GNUNET_FS_pseudonym_name_uniquify (cfg, sender, non_unique_nick, NULL);
137 GNUNET_free (non_unique_nick);
138 }
139
140 fmt = NULL;
141 switch ((int) options)
142 {
143 case GNUNET_CHAT_MSG_OPTION_NONE:
144 case GNUNET_CHAT_MSG_ANONYMOUS:
145 fmt = _("(%s) `%s' said: %s\n");
146 break;
147 case GNUNET_CHAT_MSG_PRIVATE:
148 fmt = _("(%s) `%s' said to you: %s\n");
149 break;
150 case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ANONYMOUS:
151 fmt = _("(%s) `%s' said to you: %s\n");
152 break;
153 case GNUNET_CHAT_MSG_AUTHENTICATED:
154 fmt = _("(%s) `%s' said for sure: %s\n");
155 break;
156 case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_AUTHENTICATED:
157 fmt = _("(%s) `%s' said to you for sure: %s\n");
158 break;
159 case GNUNET_CHAT_MSG_ACKNOWLEDGED:
160 fmt = _("(%s) `%s' was confirmed that you received: %s\n");
161 break;
162 case GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED:
163 fmt = _("(%s) `%s' was confirmed that you and only you received: %s\n");
164 break;
165 case GNUNET_CHAT_MSG_AUTHENTICATED | GNUNET_CHAT_MSG_ACKNOWLEDGED:
166 fmt = _("(%s) `%s' was confirmed that you received from him or her: %s\n");
167 break;
168 case GNUNET_CHAT_MSG_AUTHENTICATED | GNUNET_CHAT_MSG_PRIVATE | GNUNET_CHAT_MSG_ACKNOWLEDGED:
169 fmt =
170 _
171 ("(%s) `%s' was confirmed that you and only you received from him or her: %s\n");
172 break;
173 case GNUNET_CHAT_MSG_OFF_THE_RECORD:
174 fmt = _("(%s) `%s' said off the record: %s\n");
175 break;
176 default:
177 fmt = _("(%s) <%s> said using an unknown message type: %s\n");
178 break;
179 }
180 timestr = GNUNET_STRINGS_absolute_time_to_string (timestamp);
181 FPRINTF (stdout, fmt, timestr, nick, message);
182 GNUNET_free (nick);
183 return GNUNET_OK;
184}
185
186
187/**
188 * Callback used for message delivery confirmations.
189 *
190 * @param cls closure, NULL
191 * @param room in which room was the message received?
192 * @param orig_seq_number sequence number of the original message
193 * @param timestamp when was the message received?
194 * @param receiver who is confirming the receipt?
195 * @return GNUNET_OK to continue, GNUNET_SYSERR to refuse processing further
196 * confirmations from anyone for this message
197 */
198static int
199confirmation_cb (void *cls, struct GNUNET_CHAT_Room *room,
200 uint32_t orig_seq_number,
201 struct GNUNET_TIME_Absolute timestamp,
202 const struct GNUNET_HashCode * receiver)
203{
204 char *nick;
205 char *unique_nick;
206 int nick_is_a_dup;
207
208 if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
209 receiver, NULL, NULL, &nick, &nick_is_a_dup)
210 || (nick_is_a_dup == GNUNET_YES))
211 {
212 GNUNET_free (nick);
213 nick = GNUNET_strdup (_("anonymous"));
214 }
215 unique_nick = GNUNET_FS_pseudonym_name_uniquify (cfg, receiver, nick, NULL);
216 GNUNET_free (nick);
217 FPRINTF (stdout, _("'%s' acknowledged message #%d\n"), unique_nick, orig_seq_number);
218 GNUNET_free (unique_nick);
219 return GNUNET_OK;
220}
221
222
223/**
224 * Callback used for notification that another room member has joined or left.
225 *
226 * @param cls closure (not used)
227 * @param member_info will be non-null if the member is joining, NULL if he is
228 * leaving
229 * @param member_id hash of public key of the user (for unique identification)
230 * @param options what types of messages is this member willing to receive?
231 * @return GNUNET_OK
232 */
233static int
234member_list_cb (void *cls, const struct GNUNET_CONTAINER_MetaData *member_info,
235 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *member_id,
236 enum GNUNET_CHAT_MsgOptions options)
237{
238 char *nick;
239 char *non_unique_nick;
240 int nick_is_a_dup;
241 struct GNUNET_HashCode id;
242 struct UserList *pos;
243 struct UserList *prev;
244
245 GNUNET_CRYPTO_hash (member_id,
246 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
247 &id);
248 if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
249 &id, NULL, NULL, &non_unique_nick, &nick_is_a_dup)
250 || (nick_is_a_dup == GNUNET_YES))
251 {
252 GNUNET_free (non_unique_nick);
253 non_unique_nick = GNUNET_strdup (_("anonymous"));
254 }
255 nick = GNUNET_FS_pseudonym_name_uniquify (cfg, &id, non_unique_nick, NULL);
256 GNUNET_free (non_unique_nick);
257
258 FPRINTF (stdout,
259 member_info !=
260 NULL ? _("`%s' entered the room\n") : _("`%s' left the room\n"),
261 nick);
262 GNUNET_free (nick);
263 if (NULL != member_info)
264 {
265 /* user joining */
266 pos = GNUNET_malloc (sizeof (struct UserList));
267 pos->next = users;
268 pos->pkey = *member_id;
269 pos->ignored = GNUNET_NO;
270 users = pos;
271 }
272 else
273 {
274 /* user leaving */
275 prev = NULL;
276 pos = users;
277 while ((NULL != pos) &&
278 (0 !=
279 memcmp (&pos->pkey, member_id,
280 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded))))
281 {
282 prev = pos;
283 pos = pos->next;
284 }
285 if (NULL == pos)
286 {
287 GNUNET_break (0);
288 }
289 else
290 {
291 if (NULL == prev)
292 users = pos->next;
293 else
294 prev->next = pos->next;
295 GNUNET_free (pos);
296 }
297 }
298 return GNUNET_OK;
299}
300
301
302static int
303do_join (const char *arg, const void *xtra)
304{
305 char *my_name;
306 int my_name_is_a_dup;
307 struct GNUNET_HashCode me;
308
309 if (arg[0] == '#')
310 arg++; /* ignore first hash */
311 GNUNET_CHAT_leave_room (room);
312 free_user_list ();
313 GNUNET_free (room_name);
314 room_name = GNUNET_strdup (arg);
315 room =
316 GNUNET_CHAT_join_room (cfg, nickname, meta, room_name, -1, &join_cb, NULL,
317 &receive_cb, NULL, &member_list_cb, NULL,
318 &confirmation_cb, NULL, &me);
319 if (NULL == room)
320 {
321 FPRINTF (stdout, "%s", _("Could not change username\n"));
322 return GNUNET_SYSERR;
323 }
324 if ((GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
325 &me, NULL, NULL, &my_name, &my_name_is_a_dup)) ||
326 (my_name_is_a_dup == GNUNET_YES))
327 {
328 GNUNET_free (my_name);
329 my_name = GNUNET_strdup (_("anonymous"));
330 }
331 /* Don't uniquify our own name - other people will have a different
332 * suffix for our own name anyway.
333 */
334 FPRINTF (stdout, _("Joining room `%s' as user `%s'...\n"), room_name,
335 my_name);
336 GNUNET_free (my_name);
337 return GNUNET_OK;
338}
339
340
341static int
342do_nick (const char *msg, const void *xtra)
343{
344 char *my_name;
345 int my_name_is_a_dup;
346 struct GNUNET_HashCode me;
347
348 GNUNET_CHAT_leave_room (room);
349 free_user_list ();
350 GNUNET_free (nickname);
351 GNUNET_CONTAINER_meta_data_destroy (meta);
352 nickname = GNUNET_strdup (msg);
353 meta = GNUNET_CONTAINER_meta_data_create ();
354 GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", EXTRACTOR_METATYPE_TITLE,
355 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
356 nickname, strlen (nickname) + 1);
357 room =
358 GNUNET_CHAT_join_room (cfg, nickname, meta, room_name, -1, &join_cb, NULL,
359 &receive_cb, NULL, &member_list_cb, NULL,
360 &confirmation_cb, NULL, &me);
361 if (NULL == room)
362 {
363 FPRINTF (stdout, "%s", _("Could not change username\n"));
364 return GNUNET_SYSERR;
365 }
366 if ((GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
367 &me, NULL, NULL, &my_name, &my_name_is_a_dup)) ||
368 (my_name_is_a_dup == GNUNET_YES))
369 {
370 GNUNET_free (my_name);
371 my_name = GNUNET_strdup (_("anonymous"));
372 }
373 FPRINTF (stdout, _("Changed username to `%s'\n"), my_name);
374 GNUNET_free (my_name);
375 return GNUNET_OK;
376}
377
378
379static int
380do_names (const char *msg, const void *xtra)
381{
382 char *name;
383 char *unique_name;
384 int name_is_a_dup;
385 struct UserList *pos;
386 struct GNUNET_HashCode pid;
387
388 FPRINTF (stdout, _("Users in room `%s': "), room_name);
389 pos = users;
390 while (NULL != pos)
391 {
392 GNUNET_CRYPTO_hash (&pos->pkey,
393 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
394 &pid);
395 if (GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
396 &pid, NULL, NULL, &name, &name_is_a_dup)
397 || (name_is_a_dup == GNUNET_YES))
398 {
399 GNUNET_free (name);
400 name = GNUNET_strdup (_("anonymous"));
401 }
402 unique_name = GNUNET_FS_pseudonym_name_uniquify (cfg, &pid, name, NULL);
403 GNUNET_free (name);
404 FPRINTF (stdout, "`%s' ", unique_name);
405 GNUNET_free (unique_name);
406 pos = pos->next;
407 }
408 FPRINTF (stdout, "%s", "\n");
409 return GNUNET_OK;
410}
411
412
413static int
414do_send (const char *msg, const void *xtra)
415{
416 uint32_t seq;
417
418 GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_OPTION_NONE, NULL, &seq);
419 return GNUNET_OK;
420}
421
422
423static int
424do_send_pm (const char *msg, const void *xtra)
425{
426 char *user;
427 struct GNUNET_HashCode uid;
428 struct GNUNET_HashCode pid;
429 uint32_t seq;
430 struct UserList *pos;
431
432 if (NULL == strstr (msg, " "))
433 {
434 FPRINTF (stderr, "%s", _("Syntax: /msg USERNAME MESSAGE"));
435 return GNUNET_OK;
436 }
437 user = GNUNET_strdup (msg);
438 strstr (user, " ")[0] = '\0';
439 msg += strlen (user) + 1;
440 if (GNUNET_OK != GNUNET_FS_pseudonym_name_to_id (cfg, user, &uid))
441 {
442 FPRINTF (stderr,
443 _("Unknown user `%s'. Make sure you specify its numeric suffix, if any.\n"),
444 user);
445 GNUNET_free (user);
446 return GNUNET_OK;
447 }
448 pos = users;
449 while (NULL != pos)
450 {
451 GNUNET_CRYPTO_hash (&pos->pkey,
452 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
453 &pid);
454 if (0 == memcmp (&pid, &uid, sizeof (struct GNUNET_HashCode)))
455 break;
456 pos = pos->next;
457 }
458 if (NULL == pos)
459 {
460 FPRINTF (stderr, _("User `%s' is currently not in the room!\n"), user);
461 GNUNET_free (user);
462 return GNUNET_OK;
463 }
464 GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_PRIVATE, &pos->pkey,
465 &seq);
466 GNUNET_free (user);
467 return GNUNET_OK;
468}
469
470
471static int
472do_send_sig (const char *msg, const void *xtra)
473{
474 uint32_t seq;
475
476 GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_AUTHENTICATED, NULL,
477 &seq);
478 return GNUNET_OK;
479}
480
481
482static int
483do_send_ack (const char *msg, const void *xtra)
484{
485 uint32_t seq;
486
487 GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_ACKNOWLEDGED, NULL,
488 &seq);
489 return GNUNET_OK;
490}
491
492
493static int
494do_send_anonymous (const char *msg, const void *xtra)
495{
496 uint32_t seq;
497
498 GNUNET_CHAT_send_message (room, msg, GNUNET_CHAT_MSG_ANONYMOUS, NULL, &seq);
499 return GNUNET_OK;
500}
501
502
503static int
504do_quit (const char *args, const void *xtra)
505{
506 return GNUNET_SYSERR;
507}
508
509
510static int
511do_unknown (const char *msg, const void *xtra)
512{
513 FPRINTF (stderr, _("Unknown command `%s'\n"), msg);
514 return GNUNET_OK;
515}
516
517
518/**
519 * List of supported IRC commands. The order matters!
520 */
521static struct ChatCommand commands[] = {
522 {"/join ", &do_join,
523 gettext_noop
524 ("Use `/join #roomname' to join a chat room. Joining a room will cause you"
525 " to leave the current room")},
526 {"/nick ", &do_nick,
527 gettext_noop
528 ("Use `/nick nickname' to change your nickname. This will cause you to"
529 " leave the current room and immediately rejoin it with the new name.")},
530 {"/msg ", &do_send_pm,
531 gettext_noop
532 ("Use `/msg nickname message' to send a private message to the specified"
533 " user")},
534 {"/notice ", &do_send_pm,
535 gettext_noop ("The `/notice' command is an alias for `/msg'")},
536 {"/query ", &do_send_pm,
537 gettext_noop ("The `/query' command is an alias for `/msg'")},
538 {"/sig ", &do_send_sig,
539 gettext_noop ("Use `/sig message' to send a signed public message")},
540 {"/ack ", &do_send_ack,
541 gettext_noop
542 ("Use `/ack message' to require signed acknowledgment of the message")},
543 {"/anonymous ", &do_send_anonymous,
544 gettext_noop
545 ("Use `/anonymous message' to send a public anonymous message")},
546 {"/anon ", &do_send_anonymous,
547 gettext_noop ("The `/anon' command is an alias for `/anonymous'")},
548 {"/quit", &do_quit,
549 gettext_noop ("Use `/quit' to terminate gnunet-chat")},
550 {"/leave", &do_quit,
551 gettext_noop ("The `/leave' command is an alias for `/quit'")},
552 {"/names", &do_names,
553 gettext_noop
554 ("Use `/names' to list all of the current members in the chat room")},
555 {"/help", &do_help,
556 gettext_noop ("Use `/help command' to get help for a specific command")},
557 /* Add standard commands:
558 * /whois (print metadata),
559 * /ignore (set flag, check on receive!) */
560 /* the following three commands must be last! */
561 {"/", &do_unknown, NULL},
562 {"", &do_send, NULL},
563 {NULL, NULL, NULL},
564};
565
566
567static int
568do_help (const char *args, const void *xtra)
569{
570 int i;
571
572 i = 0;
573 while ((NULL != args) && (0 != strlen (args)) &&
574 (commands[i].Action != &do_help))
575 {
576 if (0 == strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
577 {
578 FPRINTF (stdout, "%s\n", gettext (commands[i].helptext));
579 return GNUNET_OK;
580 }
581 i++;
582 }
583 i = 0;
584 FPRINTF (stdout, "%s", "Available commands:");
585 while (commands[i].Action != &do_help)
586 {
587 FPRINTF (stdout, " %s", gettext (commands[i].command));
588 i++;
589 }
590 FPRINTF (stdout, "%s", "\n");
591 FPRINTF (stdout, "%s\n", gettext (commands[i].helptext));
592 return GNUNET_OK;
593}
594
595
596static void
597do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
598{
599 GNUNET_CHAT_leave_room (room);
600 if (handle_cmd_task != GNUNET_SCHEDULER_NO_TASK)
601 {
602 GNUNET_SCHEDULER_cancel (handle_cmd_task);
603 handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
604 }
605 free_user_list ();
606 GNUNET_CONTAINER_meta_data_destroy (meta);
607 GNUNET_free (room_name);
608 GNUNET_free (nickname);
609}
610
611
612void
613handle_command (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
614{
615 char message[MAX_MESSAGE_LENGTH + 1];
616 int i;
617
618 /* read message from command line and handle it */
619 memset (message, 0, MAX_MESSAGE_LENGTH + 1);
620 if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
621 goto next;
622 if (strlen (message) == 0)
623 goto next;
624 if (message[strlen (message) - 1] == '\n')
625 message[strlen (message) - 1] = '\0';
626 if (strlen (message) == 0)
627 goto next;
628 i = 0;
629 while ((NULL != commands[i].command) &&
630 (0 !=
631 strncasecmp (commands[i].command, message,
632 strlen (commands[i].command))))
633 i++;
634 if (GNUNET_OK !=
635 commands[i].Action (&message[strlen (commands[i].command)], NULL))
636 goto out;
637
638next:
639 handle_cmd_task =
640 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_multiply
641 (GNUNET_TIME_UNIT_MILLISECONDS, 100),
642 GNUNET_SCHEDULER_PRIORITY_UI,
643 &handle_command, NULL);
644 return;
645
646out:
647 handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
648 GNUNET_SCHEDULER_shutdown ();
649}
650
651
652/**
653 * Main function that will be run by the scheduler.
654 *
655 * @param cls closure, NULL
656 * @param args remaining command-line arguments
657 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
658 * @param c configuration
659 */
660static void
661run (void *cls, char *const *args, const char *cfgfile,
662 const struct GNUNET_CONFIGURATION_Handle *c)
663{
664 struct GNUNET_HashCode me;
665 char *my_name;
666 int my_name_is_a_dup;
667
668 cfg = c;
669 /* check arguments */
670 if (NULL == nickname)
671 {
672 FPRINTF (stderr, "%s", _("You must specify a nickname\n"));
673 ret = -1;
674 return;
675 }
676 if (NULL == room_name)
677 room_name = GNUNET_strdup ("gnunet");
678 meta = GNUNET_CONTAINER_meta_data_create ();
679 GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", EXTRACTOR_METATYPE_TITLE,
680 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
681 nickname, strlen (nickname) + 1);
682 room =
683 GNUNET_CHAT_join_room (cfg, nickname, meta, room_name, -1, &join_cb, NULL,
684 &receive_cb, NULL, &member_list_cb, NULL,
685 &confirmation_cb, NULL, &me);
686 if (NULL == room)
687 {
688 FPRINTF (stderr, _("Failed to join room `%s'\n"), room_name);
689 GNUNET_free (room_name);
690 GNUNET_free (nickname);
691 GNUNET_CONTAINER_meta_data_destroy (meta);
692 ret = -1;
693 return;
694 }
695 if ((GNUNET_OK != GNUNET_FS_pseudonym_get_info (cfg,
696 &me, NULL, NULL, &my_name, &my_name_is_a_dup)) ||
697 (my_name_is_a_dup == GNUNET_YES))
698 {
699 GNUNET_free (my_name);
700 my_name = GNUNET_strdup (_("anonymous"));
701 }
702 FPRINTF (stdout, _("Joining room `%s' as user `%s'...\n"), room_name,
703 my_name);
704 GNUNET_free (my_name);
705 handle_cmd_task =
706 GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI,
707 &handle_command, NULL);
708 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
709 NULL);
710}
711
712
713/**
714 * The main function to chat via GNUnet.
715 *
716 * @param argc number of arguments from the command line
717 * @param argv command line arguments
718 * @return 0 ok, 1 on error
719 */
720int
721main (int argc, char *const *argv)
722{
723 int flags;
724
725 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
726 {'n', "nick", "NAME",
727 gettext_noop ("set the nickname to use (required)"),
728 1, &GNUNET_GETOPT_set_string, &nickname},
729 {'r', "room", "NAME",
730 gettext_noop ("set the chat room to join"),
731 1, &GNUNET_GETOPT_set_string, &room_name},
732 GNUNET_GETOPT_OPTION_END
733 };
734
735#ifndef WINDOWS
736 flags = fcntl (0, F_GETFL, 0);
737 flags |= O_NONBLOCK;
738 fcntl (0, F_SETFL, flags);
739#endif
740
741 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
742 return 2;
743
744 return (GNUNET_OK ==
745 GNUNET_PROGRAM_run (argc, argv, "gnunet-chat",
746 gettext_noop ("Join a chat on GNUnet."), options,
747 &run, NULL)) ? ret : 1;
748}
749
750/* end of gnunet-chat.c */