]> sjero.net Git - linphone/blob - console/commands.c
Merge branch 'master' into dev_multicall
[linphone] / console / commands.c
1 /****************************************************************************
2  *
3  *  $Id: commands.c,v 1.39 2008/07/03 15:08:34 smorlat Exp $
4  *
5  *  Copyright (C) 2006-2009  Sandro Santilli <strk@keybit.net>
6  *  Copyright (C) 2004  Simon MORLAT <simon.morlat@linphone.org>
7  *
8 ****************************************************************************
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  *
24  ****************************************************************************/
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #ifndef _WIN32_WCE
30 #include <errno.h>
31 #include <unistd.h>
32 #endif /*_WIN32_WCE*/
33 #include <limits.h>
34 #include <ctype.h>
35 #include <linphonecore.h>
36 #include "linphonec.h"
37 #include "private.h"
38 #include "lpconfig.h"
39
40 #ifndef WIN32
41 #include <sys/wait.h>
42 #endif
43
44 /***************************************************************************
45  *
46  *  Forward declarations 
47  *
48  ***************************************************************************/
49
50 extern char *lpc_strip_blanks(char *input);
51
52 /* Command handlers */
53 static int lpc_cmd_help(LinphoneCore *, char *);
54 static int lpc_cmd_proxy(LinphoneCore *, char *);
55 static int lpc_cmd_call(LinphoneCore *, char *);
56 static int lpc_cmd_chat(LinphoneCore *, char *);
57 static int lpc_cmd_answer(LinphoneCore *, char *);
58 static int lpc_cmd_autoanswer(LinphoneCore *, char *);
59 static int lpc_cmd_terminate(LinphoneCore *, char *);
60 static int lpc_cmd_call_logs(LinphoneCore *, char *);
61 static int lpc_cmd_ipv6(LinphoneCore *, char *);
62 static int lpc_cmd_refer(LinphoneCore *, char *);
63 static int lpc_cmd_quit(LinphoneCore *, char *);
64 static int lpc_cmd_nat(LinphoneCore *, char *);
65 static int lpc_cmd_stun(LinphoneCore *, char *);
66 static int lpc_cmd_firewall(LinphoneCore *, char *);
67 static int lpc_cmd_friend(LinphoneCore *, char*);
68 static int lpc_cmd_soundcard(LinphoneCore *, char *);
69 static int lpc_cmd_webcam(LinphoneCore *, char *);
70 static int lpc_cmd_staticpic(LinphoneCore *, char *);
71 static int lpc_cmd_play(LinphoneCore *, char *);
72 static int lpc_cmd_record(LinphoneCore *, char *);
73 static int lpc_cmd_register(LinphoneCore *, char *);
74 static int lpc_cmd_unregister(LinphoneCore *, char *);
75 static int lpc_cmd_duration(LinphoneCore *lc, char *args);
76 static int lpc_cmd_status(LinphoneCore *lc, char *args);
77 static int lpc_cmd_ports(LinphoneCore *lc, char *args);
78 static int lpc_cmd_speak(LinphoneCore *lc, char *args);
79 static int lpc_cmd_codec(LinphoneCore *lc, char *args);
80 static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args);
81 static int lpc_cmd_pause(LinphoneCore *lc, char *args);
82 static int lpc_cmd_resume(LinphoneCore *lc, char *args);
83
84 /* Command handler helpers */
85 static void linphonec_proxy_add(LinphoneCore *lc);
86 static void linphonec_proxy_display(LinphoneProxyConfig *lc);
87 static void linphonec_proxy_list(LinphoneCore *lc);
88 static void linphonec_proxy_remove(LinphoneCore *lc, int index);
89 static  int linphonec_proxy_use(LinphoneCore *lc, int index);
90 static void linphonec_proxy_show(LinphoneCore *lc,int index);
91 static void linphonec_friend_display(LinphoneFriend *fr);
92 static int linphonec_friend_list(LinphoneCore *lc, char *arg);
93 static void linphonec_display_command_help(LPC_COMMAND *cmd);
94 static int linphonec_friend_call(LinphoneCore *lc, unsigned int num);
95 #ifndef WIN32
96 static int linphonec_friend_add(LinphoneCore *lc, const char *name, const char *addr);
97 #endif
98 static int linphonec_friend_delete(LinphoneCore *lc, int num);
99 static int linphonec_friend_delete(LinphoneCore *lc, int num);
100 static void linphonec_codec_list(LinphoneCore *lc);
101 static void linphonec_codec_enable(LinphoneCore *lc, int index);
102 static void linphonec_codec_disable(LinphoneCore *lc, int index);
103
104
105
106 /* Command table management */
107 static LPC_COMMAND *lpc_find_command(const char *name);
108
109 void linphonec_out(const char *fmt,...);
110
111
112
113 /***************************************************************************
114  *
115  *  Global variables
116  *
117  ***************************************************************************/
118
119 /*
120  * Commands table.
121  */
122 LPC_COMMAND commands[] = {
123         { "help", lpc_cmd_help, "Print commands help", NULL },
124         { "call", lpc_cmd_call, "Call a SIP uri",
125                 "'call <sip-url>' \t: initiate a call to the specified destination.\n"
126                 "'call show' \t: show all the current calls status.\n"
127                 },
128         { "chat", lpc_cmd_chat, "Chat with a SIP uri",
129                 "'chat <sip-url> \"message\"' "
130                 ": send a chat message \"message\" to the specified destination."
131                 },
132         { "terminate", lpc_cmd_terminate, "Terminate a call",
133                 "'terminate' : Terminate the current call\n"
134                 "'terminate <sip:XXX@XXX.XXX.XXX.XXX>' : Terminate the call with remote address\n"
135                 "'terminate <all>' : Terminate all the current calls\n"
136                 },
137         { "answer", lpc_cmd_answer, "Answer a call",
138                 "'answer' : Answer the current incoming call\n"
139                 "'answer <sip:XXX@XXX.XXX.XXX.XXX>' : Answer the call with remote address\n"
140         },
141         { "autoanswer", lpc_cmd_autoanswer, "Show/set auto-answer mode",
142                 "'autoanswer'       \t: show current autoanswer mode\n"
143                 "'autoanswer enable'\t: enable autoanswer mode\n"
144                 "'autoanswer disable'\t: disable autoanswer modeĀ \n"},
145         { "proxy", lpc_cmd_proxy, "Manage proxies",
146                 "'proxy list' : list all proxy setups.\n"
147                 "'proxy add' : add a new proxy setup.\n"
148                 "'proxy remove <index>' : remove proxy setup with number index.\n"
149                 "'proxy use <index>' : use proxy with number index as default proxy.\n"
150                 "'proxy unuse' : don't use a default proxy.\n"
151                 "'proxy show <index>' : show configuration and status of the proxy numbered by index.\n"
152                 "'proxy show default' : show configuration and status of the default proxy.\n"
153         },
154         { "soundcard", lpc_cmd_soundcard, "Manage soundcards",
155                 "'soundcard list' : list all sound devices.\n"
156                 "'soundcard show' : show current sound devices configuration.\n"
157                 "'soundcard use <index>' : select a sound device.\n"
158                 "'soundcard use files' : use .wav files instead of soundcard\n"
159         },
160         { "webcam", lpc_cmd_webcam, "Manage webcams",
161                 "'webcam list' : list all known devices.\n"
162                 "'webcam use <index>' : select a video device.\n"
163         },
164         { "staticpic", lpc_cmd_staticpic, "Manage static pictures when nowebcam",
165                 "'staticpic set' : Set path to picture that should be used.\n"
166         },
167         { "ipv6", lpc_cmd_ipv6, "Use IPV6",
168                 "'ipv6 status' : show ipv6 usage status.\n"
169                 "'ipv6 enable' : enable the use of the ipv6 network.\n"
170                 "'ipv6 disable' : do not use ipv6 network."
171         },
172         { "refer", lpc_cmd_refer,
173                 "Refer the current call to the specified destination.",
174                 "'refer <sip-url>' or 'r <sip-url>' "
175                 ": refer the current call to the specified destination."
176         },
177         { "nat", lpc_cmd_nat, "Set nat address",
178                 "'nat'        : show nat settings.\n"
179                 "'nat <addr>' : set nat address.\n"
180         },
181         { "stun", lpc_cmd_stun, "Set stun server address",
182                 "'stun'        : show stun settings.\n"
183                 "'stun <addr>' : set stun server address.\n"
184         },
185         { "firewall", lpc_cmd_firewall, "Set firewall policy",
186                 "'firewall'        : show current firewall policy.\n"
187                 "'firewall none'   : use direct connection.\n"
188                 "'firewall nat'    : use nat address given with the 'nat' command.\n"
189                 "'firewall stun'   : use stun server given with the 'stun' command.\n"
190         },
191         { "call-logs", lpc_cmd_call_logs, "Calls history", NULL },
192         { "friend", lpc_cmd_friend, "Manage friends",
193                 "'friend list [<pattern>]'    : list friends.\n"
194                 "'friend call <index>'        : call a friend.\n"
195                 "'friend add <name> <addr>'   : add friend, <name> must be quoted to include\n"
196             "                               spaces, <addr> has \"sip:\" added if it isn't\n"
197             "                               there.  Don't use '<' '>' around <addr>.\n"
198                 "'friend delete <index>'      : remove friend, 'all' removes all\n"
199         },
200         { "play", lpc_cmd_play, "play from a wav file",
201                 "This feature is available only in file mode (see 'help soundcard')\n"
202                 "'play <wav file>'    : play a wav file."
203         },
204         { "record", lpc_cmd_record, "record to a wav file",
205                 "This feature is available only in file mode (see 'help soundcard')\n"
206                 "'record <wav file>'    : record into wav file."
207         },
208         { "quit", lpc_cmd_quit, "Exit linphonec", NULL },
209         { "register", lpc_cmd_register, "Register in one line to a proxy" , "register <sip identity> <sip proxy> <password>"},
210         { "unregister", lpc_cmd_unregister, "Unregister from default proxy", NULL       },
211         { "duration", lpc_cmd_duration, "Print duration in seconds of the last call.", NULL },
212         { "status", lpc_cmd_status, "Print various status information", 
213                         "'status register'  \t: print status concerning registration\n"
214                         "'status autoanswer'\t: tell whether autoanswer mode is enabled\n"
215                         "'status hook'      \t: print hook status\n" },
216         { "ports", lpc_cmd_ports, "Network ports configuration", 
217                         "'ports'  \t: prints current used ports.\n"
218                         "'ports sip <port number>'\t: Sets the sip port.\n" },
219         { "speak", lpc_cmd_speak, "Speak a sentence using espeak TTS engine",
220                         "This feature is available only in file mode. (see 'help soundcard')\n"
221                         "'speak <voice name> <sentence>'        : speak a text using the specified espeak voice.\n"
222                         "Example for english voice: 'speak default Hello my friend !'"
223         },
224     { "codec", lpc_cmd_codec, "Codec configuration",
225             "'codec list' : list codecs\n"  
226             "'codec enable <index>' : enable available codec\n"  
227             "'codec disable <index>' : disable codecs" }, 
228     { "ec", lpc_cmd_echocancellation, "Echo cancellation",
229             "'ec on [<delay>] [<tail>] [<framesize>]' : turn EC on with given delay, tail length and framesize\n"
230             "'ec off' : turn echo cancellation (EC) off\n"
231             "'ec show' : show EC status" },
232     { "pause", lpc_cmd_pause, "pause a call",
233                 "'pause' : pause the current call\n"},
234     { "resume", lpc_cmd_resume, "resume a call",
235                 "'resume' : resume the unique call\n"
236                 "'resume <sip:XXX@XXX.XXX.XXX.XXX>' : hold off the call with cid <cid>\n"},
237     { (char *)NULL, (lpc_cmd_handler)NULL, (char *)NULL, (char *)NULL }
238 };
239
240 /***************************************************************************
241  *
242  *  Public interface 
243  *
244  ***************************************************************************/
245
246 /*
247  * Main command dispatcher.
248  * WARNING: modifies second argument!
249  *
250  * Always return 1 currently.
251  */
252 int
253 linphonec_parse_command_line(LinphoneCore *lc, char *cl)
254 {
255         char *ptr=cl;
256         char *args=NULL;
257         LPC_COMMAND *cmd;
258
259         /* Isolate first word and args */
260         while(*ptr && !isspace(*ptr)) ++ptr;
261         if (*ptr)
262         {
263                 *ptr='\0';
264                 /* set args to first nonblank */
265                 args=ptr+1;
266                 while(*args && isspace(*args)) ++args;
267         }
268
269         /* Handle DTMF */
270         if ( isdigit(*cl) || *cl == '#' || *cl == '*' )
271         {
272                 while ( isdigit(*cl) || *cl == '#' || *cl == '*' )
273                 {
274                         linphone_core_send_dtmf(lc, *cl);
275                         ms_sleep(1); // be nice
276                         ++cl;
277                 }
278
279                 // discard spurious trailing chars
280                 return 1;
281         }
282
283         /* Handle other kind of commands */
284         cmd=lpc_find_command(cl);
285         if ( !cmd )
286         {
287                 linphonec_out("'%s': Cannot understand this.\n", cl);
288                 return 1;
289         }
290
291         if ( ! cmd->func(lc, args) )
292         {
293                 linphonec_out("Syntax error.\n");
294                 linphonec_display_command_help(cmd);
295         }
296
297         return 1;
298 }
299
300 /*
301  * Generator function for command completion.
302  * STATE let us know whether to start from scratch;
303  * without any state (STATE==0), then we start at the
304  * top of the list.
305  */
306 char *
307 linphonec_command_generator(const char *text, int state)
308 {
309         static int index, len;
310         char *name;
311
312         if ( ! state )
313         {
314                 index=0;
315                 len=strlen(text);
316         }
317
318         /*
319          * Return the next name which partially matches
320          * from the commands list
321          */
322         while ((name=commands[index].name))
323         {
324                 ++index; /* so next call get next command */
325
326                 if (strncmp(name, text, len) == 0)
327                 {
328                         return ortp_strdup(name);
329                 }
330         }
331
332         return NULL;
333 }
334
335
336 /***************************************************************************
337  *
338  *  Command handlers 
339  *
340  ***************************************************************************/
341
342 static int
343 lpc_cmd_help(LinphoneCore *lc, char *arg)
344 {
345         int i=0;
346         LPC_COMMAND *cmd;
347
348         if (!arg || !*arg)
349         {
350                 linphonec_out("Commands are:\n");
351                 linphonec_out("---------------------------\n");
352
353                 while (commands[i].help)
354                 {
355                         linphonec_out("%10.10s\t%s\n", commands[i].name,
356                                 commands[i].help);
357                         i++;
358                 }
359                 
360                 linphonec_out("---------------------------\n");
361                 linphonec_out("Type 'help <command>' for more details.\n");
362
363                 return 1;
364         }
365
366         cmd=lpc_find_command(arg);
367         if ( !cmd )
368         {
369                 linphonec_out("No such command.\n");
370                 return 1;
371         }
372
373         linphonec_display_command_help(cmd);
374         return 1;
375
376 }
377
378 static char callee_name[256]={0};
379 static char caller_name[256]={0};
380
381 static int
382 lpc_cmd_call(LinphoneCore *lc, char *args)
383 {
384         if ( ! args || ! *args )
385         {
386                 return 0;
387         }
388         if(!strcmp(args,"show"))
389         {
390                 MSList *calls = linphone_core_get_calls(lc);
391                 if(calls)
392                 {
393                         MSList *p_calls = calls;
394                         linphonec_out("<remote>\t\t\t\t<status>\r\n");
395                         while(p_calls != NULL)                  
396                         {
397                                 linphonec_out("%s\t\t\t%s\r\n",
398                                                 linphone_call_get_remote_address_as_string(p_calls->data),
399                                                 (((LinphoneCall *)p_calls->data)==linphone_core_get_current_call(lc))?"yes":"no");
400                                 p_calls = p_calls->next;
401                         }
402                         ms_list_free(calls);
403                 }
404                 else
405                 {
406                         linphonec_out("No active call.\n");
407                 }
408         }
409         else
410         {
411                 if ( linphone_core_in_call(lc) )
412                 {
413                         linphonec_out("Terminate or hold on the current call first.\n");
414                         return 1;
415                 }
416                 if ( NULL == linphone_core_invite(lc, args) )
417                 {
418                         linphonec_out("Error from linphone_core_invite.\n");
419                 }
420                 else
421                 {
422                         snprintf(callee_name,sizeof(callee_name),"%s",args);
423                 }
424         }
425         return 1;
426 }
427
428 static int
429 lpc_cmd_chat(LinphoneCore *lc, char *args)
430 {
431         char *arg1 = args;
432         char *arg2 = NULL;
433         char *ptr = args;
434
435         if (!args) return 0;
436
437         /* Isolate first and second arg */
438         while(*ptr && !isspace(*ptr)) ++ptr;
439         if ( *ptr )
440         {
441                 *ptr='\0';
442                 arg2=ptr+1;
443                 while(*arg2 && isspace(*arg2)) ++arg2;
444         }
445         else
446         {
447                 /* missing one parameter */
448                 return 0;
449         }
450         LinphoneChatRoom *cr = linphone_core_create_chat_room(lc,arg1);
451         linphone_chat_room_send_message(cr,arg2);
452         linphone_chat_room_destroy(cr);
453
454         return 1;
455 }
456
457 const char *linphonec_get_callee(){
458         return callee_name;
459 }
460
461 const char *linphonec_get_caller(){
462         return caller_name;
463 }
464
465 void linphonec_set_caller(const char *caller){
466         snprintf(caller_name,sizeof(caller_name)-1,"%s",caller);
467 }
468
469 static int
470 lpc_cmd_refer(LinphoneCore *lc, char *args)
471 {
472         if (args)
473                 linphone_core_refer(lc, linphone_core_get_current_call(lc), args);
474         else{
475                 linphonec_out("refer needs an argument\n");
476         }
477         return 1;
478 }
479
480 static int
481 lpc_cmd_terminate(LinphoneCore *lc, char *args)
482 {
483         char *arg1 = args;
484         char *arg2 = NULL;
485         char *ptr = args;
486
487         if (!args)
488         {
489                 if(linphone_core_in_call(lc))
490                 {
491                         if ( -1 == linphone_core_terminate_call(lc, linphone_core_get_current_call(lc)) )
492                         {
493                                 linphonec_out("Could not stop the active call.\n");
494                         }
495                 }
496                 else
497                 {
498                         linphonec_out("No active call.\n");
499                 }
500                 return 1;
501         }
502         
503         /* Isolate first and second arg */
504         while(*ptr && !isspace(*ptr)) ++ptr;
505         if ( *ptr )
506         {
507                 *ptr='\0';
508                 arg2=ptr+1;
509                 while(*arg2 && isspace(*arg2)) ++arg2;
510         }
511         if (arg1 != 0)
512         {
513                 if(strcmp(arg1,"all")==0)
514                 {
515                         linphonec_out("We are going to stop all the calls.\n");
516                         return (linphone_core_terminate_all_calls(lc)==0)?1:0;
517                 }
518                 else
519                 {
520                         char the_remote_address[255];
521                         int n = sscanf(arg1, "%s", the_remote_address);
522                         if (n == 1)
523                         {
524                                 if ( -1 == linphone_core_terminate_call(lc,linphone_core_get_call_by_remote_address(lc,the_remote_address)))
525                                 {
526                                         linphonec_out("Cannot stop the call with %s.\n",the_remote_address);
527                                 }
528                                 return 1;
529                         }
530                 }
531         }
532         return 0;
533         
534 }
535
536 static int
537 lpc_cmd_answer(LinphoneCore *lc, char *args)
538 {
539         char *arg1 = args;
540         char *arg2 = NULL;
541         char *ptr = args;
542
543         if (!args)
544         {
545                 //if just one call is present answer the only one in passing NULL to the linphone_core_accept_call ...
546                 if ( -1 == linphone_core_accept_call(lc, NULL) )
547                 {
548                         linphonec_out("No incoming call.\n");
549                 }
550                 return 1;
551         }
552
553         // Isolate first and second arg
554         while(*ptr && !isspace(*ptr)) ++ptr;
555         if ( *ptr )
556         {
557                 *ptr='\0';
558                 arg2=ptr+1;
559                 while(*arg2 && isspace(*arg2)) ++arg2;
560         }
561         if (arg1 != 0)
562         {
563                 char the_remote_address[256];
564                 int n = sscanf(arg1, "%s", the_remote_address);
565                 if (n == 1)
566                 {
567                         if ( -1 == linphone_core_accept_call(lc, linphone_core_get_call_by_remote_address(lc,the_remote_address)) )
568                         {
569                                 linphonec_out("Cannot answer the call from %s.\n",the_remote_address);
570                         }
571                         return 1;
572                 }
573         }
574         return 0;
575 }
576
577 static int
578 lpc_cmd_autoanswer(LinphoneCore *lc, char *args)
579 {
580         if ( ! args )
581         {
582                 if ( linphonec_get_autoanswer() ) {
583                         linphonec_out("Auto answer is enabled. Use 'autoanswer disable' to disable.\n");
584                 } else {
585                         linphonec_out("Auto answer is disabled. Use 'autoanswer enable' to enable.\n");
586                 }
587                 return 1;
588         }
589
590         if (strstr(args,"enable")){
591                 linphonec_set_autoanswer(TRUE);
592                 linphonec_out("Auto answer enabled.\n");
593         }else if (strstr(args,"disable")){
594                 linphonec_set_autoanswer(FALSE);
595                 linphonec_out("Auto answer disabled.\n");
596         }else return 0;
597         return 1;
598 }
599
600 static int
601 lpc_cmd_quit(LinphoneCore *lc, char *args)
602 {
603         linphonec_main_loop_exit();
604         return 1;
605 }
606
607 static int
608 lpc_cmd_nat(LinphoneCore *lc, char *args)
609 {
610         bool_t use;
611         const char *nat;
612
613         if ( args ) args=lpc_strip_blanks(args);
614
615         if ( args && *args )
616         {
617                 linphone_core_set_nat_address(lc, args);
618                 /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS); */
619         }
620
621         nat = linphone_core_get_nat_address(lc);
622         use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_NAT_ADDRESS;
623         linphonec_out("Nat address: %s%s\n", nat ? nat : "unspecified" , use ? "" : " (disabled - use 'firewall nat' to enable)");
624
625         return 1;
626 }
627
628 static int
629 lpc_cmd_stun(LinphoneCore *lc, char *args)
630 {
631         bool_t use;
632         const char *stun;
633
634         if ( args ) args=lpc_strip_blanks(args);
635
636         if ( args && *args )
637         {
638                 linphone_core_set_stun_server(lc, args);
639                 /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN); */
640         }
641
642         stun = linphone_core_get_stun_server(lc);
643         use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_STUN;
644         linphonec_out("Stun server: %s%s\n", stun ? stun : "unspecified" , use? "" : " (disabled - use 'firewall stun' to enable)");
645
646         return 1;
647 }
648
649 static int
650 lpc_cmd_firewall(LinphoneCore *lc, char *args)
651 {
652         const char* setting=NULL;
653
654         if ( args ) args=lpc_strip_blanks(args);
655
656         if ( args && *args )
657         {
658                 if (strcmp(args,"none")==0)
659                 {
660                         linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_NO_FIREWALL);
661                 }
662                 else if (strcmp(args,"stun")==0)
663                 {
664                         setting = linphone_core_get_stun_server(lc);
665                         if ( ! setting )
666                         {
667                                 linphonec_out("No stun server address is defined, use 'stun <address>' first\n");
668                                 return 1;
669                         }
670                         linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN);
671                 }
672                 else if (strcmp(args,"nat")==0)
673                 {
674                         setting = linphone_core_get_nat_address(lc);
675                         if ( ! setting )
676                         {
677                                 linphonec_out("No nat address is defined, use 'nat <address>' first");
678                                 return 1;
679                         }
680                         linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS);
681                 }
682         }
683
684         switch(linphone_core_get_firewall_policy(lc))
685         {
686                 case LINPHONE_POLICY_NO_FIREWALL:
687                         linphonec_out("No firewall\n");
688                         break;
689                 case LINPHONE_POLICY_USE_STUN:
690                         linphonec_out("Using stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
691                         break;
692                 case LINPHONE_POLICY_USE_NAT_ADDRESS:
693                         linphonec_out("Using supplied nat address %s.\n", setting ? setting : linphone_core_get_nat_address(lc));
694                         break;
695         }
696         return 1;
697 }
698
699 #ifndef WIN32
700 /* Helper function for processing freind names */
701 static int
702 lpc_friend_name(char **args, char **name)
703 {
704         /* Use space as a terminator unless quoted */
705         if (('"' == **args) || ('\'' == **args)){
706                 char *end;
707                 char delim = **args;
708                 (*args)++;
709                 end = (*args);
710                 while ((delim != *end) && ('\0' != *end)) end++;
711                 if ('\0' == *end) {
712                         fprintf(stderr, "Mismatched quotes\n");
713                         return 0;
714                 }
715                 *name = *args;
716                 *end = '\0';
717                 *args = ++end;
718         } else {
719                 *name = strsep(args, " ");
720                 
721                 if (NULL == *args) { /* Means there was no separator */
722                         fprintf(stderr, "Either name or address is missing\n");
723                         return 0;
724                 }
725                 if (NULL == *name) return 0;
726         }
727         return 1;
728 }
729 #endif
730
731 static int
732 lpc_cmd_friend(LinphoneCore *lc, char *args)
733 {
734         int friend_num;
735
736         if ( args ) args=lpc_strip_blanks(args);
737
738         if ( ! args || ! *args ) return 0;
739
740         if ( !strncmp(args, "list", 4) )
741         {
742                 return linphonec_friend_list(lc, args+4);
743                 return 1;
744         }
745         else if ( !strncmp(args, "call", 4) )
746         {
747                 args+=4;
748                 if ( ! *args ) return 0;
749                 friend_num = strtol(args, NULL, 10);
750 #ifndef _WIN32_WCE              
751                 if ( errno == ERANGE ) {
752                         linphonec_out("Invalid friend number\n");
753                         return 0;
754                 }
755 #endif /*_WIN32_WCE*/
756                 linphonec_friend_call(lc, friend_num);
757                 return 1;
758         }
759         else if ( !strncmp(args, "delete", 6) )
760         {
761                 args+=6;
762                 if ( ! *args ) return 0;
763                 while (*args == ' ') args++;
764                 if ( ! *args ) return 0;
765                 if (!strncmp(args, "all", 3))
766                 {
767                         friend_num = -1;
768                 } 
769                 else
770                 {
771                         friend_num = strtol(args, NULL, 10);
772 #ifndef _WIN32_WCE              
773                         if ( errno == ERANGE ) {
774                                 linphonec_out("Invalid friend number\n");
775                                 return 0;
776                         }
777 #endif /*_WIN32_WCE*/
778                 }
779                 linphonec_friend_delete(lc, friend_num);
780                 return 1;
781         }
782         else if ( !strncmp(args, "add", 3) )
783         {
784 #ifndef WIN32
785                 char  *name;
786                 char  addr[80];
787                 char *addr_p = addr;
788                 char *addr_orig;
789
790                 args+=3;
791                 if ( ! *args ) return 0;
792                 while (*args == ' ') args++;
793                 if ( ! *args ) return 0;
794
795                 if (!lpc_friend_name(&args,  &name)) return 0;
796
797                 while (*args == ' ') args++;
798                 if ( ! *args ) return 0;
799                 if (isdigit(*args)) {
800                         strcpy (addr, "sip:");
801                         addr_p = addr + strlen("sip:");
802                 }
803                 addr_orig = strsep(&args, " ");
804                 if (1 >= strlen(addr_orig)) {
805                         fprintf(stderr, "A single-digit address is not valid\n");
806                         return 0;
807                 }
808                 strcpy(addr_p, addr_orig);
809                 linphonec_friend_add(lc, name, addr);
810 #else
811                 LinphoneFriend *new_friend;
812                 new_friend = linphone_friend_new_with_addr(args);
813                 linphone_core_add_friend(lc, new_friend);
814 #endif
815                 return 1;
816         }
817         return 0;
818 }
819
820 static int lpc_cmd_play(LinphoneCore *lc, char *args){
821         if ( args ) args=lpc_strip_blanks(args);
822         if ( ! args || ! *args ) return 0;
823         linphone_core_set_play_file(lc,args);
824         return 1;
825 }
826
827 static int lpc_cmd_record(LinphoneCore *lc, char *args){
828         if ( args ) args=lpc_strip_blanks(args);
829         if ( ! args || ! *args ) return 0;
830         linphone_core_set_record_file(lc,args);
831         return 1;
832 }
833
834 /*
835  * Modified input
836  */
837 static int
838 lpc_cmd_proxy(LinphoneCore *lc, char *args)
839 {
840         char *arg1 = args;
841         char *arg2 = NULL;
842         char *ptr = args;
843         int proxynum;
844
845         if ( ! arg1 ) return 0;
846
847         /* Isolate first and second arg */
848         while(*ptr && !isspace(*ptr)) ++ptr;
849         if ( *ptr )
850         {
851                 *ptr='\0';
852                 arg2=ptr+1;
853                 while(*arg2 && isspace(*arg2)) ++arg2;
854         }
855
856         if (strcmp(arg1,"add")==0)
857         {
858 #ifdef HAVE_READLINE
859                 rl_inhibit_completion=1;
860 #endif
861                 linphonec_proxy_add(lc);
862 #ifdef HAVE_READLINE
863                 rl_inhibit_completion=0;
864 #endif
865         }
866         else if (strcmp(arg1,"list")==0)
867         {
868                 linphonec_proxy_list(lc);
869         }
870         else if (strcmp(arg1,"remove")==0)
871         {
872                 linphonec_proxy_remove(lc,atoi(arg2));
873         }
874         else if (strcmp(arg1,"use")==0)
875         {
876                 if ( arg2 && *arg2 )
877                 {
878                         proxynum=atoi(arg2);
879                         if ( linphonec_proxy_use(lc, proxynum) )
880                                 linphonec_out("Default proxy set to %d.\n", proxynum);
881                 }
882                 else
883                 {
884                         proxynum=linphone_core_get_default_proxy(lc, NULL);
885                         if ( proxynum == -1 ) linphonec_out("No default proxy.\n");
886                         else linphonec_out("Current default proxy is %d.\n", proxynum);
887                 }
888         }else if (strcmp(arg1, "unuse")==0){
889                 linphone_core_set_default_proxy(lc, NULL);
890                 linphonec_out("Use no proxy.\n");
891         }
892
893         else if (strcmp(arg1, "show")==0)
894         {
895                 if (arg2 && *arg2)
896                 {
897                         if (strstr(arg2,"default"))
898                         {
899                 proxynum=linphone_core_get_default_proxy(lc, NULL);
900                 if ( proxynum < 0 ) {
901                         linphonec_out("No default proxy defined\n");
902                         return 1;
903                 }
904                 linphonec_proxy_show(lc,proxynum);
905                         }
906                         else
907                         {
908                 linphonec_proxy_show(lc, atoi(arg2));
909                         }
910                 }
911                 else return 0; /* syntax error */
912         }
913
914         else
915         {
916                 return 0; /* syntax error */
917         }
918
919         return 1;
920 }
921
922 static int
923 lpc_cmd_call_logs(LinphoneCore *lc, char *args)
924 {
925         const MSList *elem=linphone_core_get_call_logs(lc);
926         for (;elem!=NULL;elem=ms_list_next(elem))
927         {
928                 LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
929                 char *str=linphone_call_log_to_str(cl);
930                 linphonec_out("%s\n",str);
931                 ms_free(str);
932         }
933         return 1;
934 }
935
936 static int
937 lpc_cmd_ipv6(LinphoneCore *lc, char *arg1)
938 {
939         if ( ! arg1 )
940         {
941                 return 0; /* syntax error */
942         }
943
944         if (strcmp(arg1,"status")==0)
945         {
946                 linphonec_out("ipv6 use enabled: %s\n",linphone_core_ipv6_enabled(lc) ? "true":"false");
947         }
948         else if (strcmp(arg1,"enable")==0)
949         {
950                 linphone_core_enable_ipv6(lc,TRUE);
951                 linphonec_out("ipv6 use enabled.\n");
952         }
953         else if (strcmp(arg1,"disable")==0)
954         {
955                 linphone_core_enable_ipv6(lc,FALSE);
956                 linphonec_out("ipv6 use disabled.\n");
957         }
958         else
959         {
960                 return 0; /* syntax error */
961         }
962         return 1;
963 }
964
965 static int devname_to_index(LinphoneCore *lc, const char *devname){
966         const char **p;
967         int i;
968         for(i=0,p=linphone_core_get_sound_devices(lc);*p!=NULL;++p,++i){
969                 if (strcmp(devname,*p)==0) return i;
970         }
971         return -1;
972 }
973
974 static const char *index_to_devname(LinphoneCore *lc, int index){
975         const char **p;
976         int i;
977         for(i=0,p=linphone_core_get_sound_devices(lc);*p!=NULL;++p,++i){
978                 if (i==index) return *p;
979         }
980         return NULL;
981 }
982
983 static int lpc_cmd_soundcard(LinphoneCore *lc, char *args)
984 {
985         int i, index;
986         const char **dev;
987         char *arg1 = args;
988         char *arg2 = NULL;
989         char *ptr = args;
990
991         if (!args) return 0; /* syntax error */
992
993         /* Isolate first and second arg */
994         while(*ptr && !isspace(*ptr)) ++ptr;
995         if ( *ptr )
996         {
997                 *ptr='\0';
998                 arg2=ptr+1;
999                 while(*arg2 && isspace(*arg2)) ++arg2;
1000         }
1001
1002         if (strcmp(arg1, "list")==0)
1003         {
1004                 dev=linphone_core_get_sound_devices(lc);
1005                 for(i=0; dev[i]!=NULL; ++i){
1006                         linphonec_out("%i: %s\n",i,dev[i]);
1007                 }
1008                 return 1;
1009         }
1010
1011         if (strcmp(arg1, "show")==0)
1012         {
1013                 linphonec_out("Ringer device: %s\n",
1014                         linphone_core_get_ringer_device(lc));
1015                 linphonec_out("Playback device: %s\n",
1016                         linphone_core_get_playback_device(lc));
1017                 linphonec_out("Capture device: %s\n",
1018                         linphone_core_get_capture_device(lc));
1019                 return 1;
1020         }
1021
1022         if (strcmp(arg1, "use")==0 && arg2)
1023         {
1024                 if (strcmp(arg2, "files")==0)
1025                 {
1026                         linphonec_out("Using wav files instead of soundcard.\n");
1027                         linphone_core_use_files(lc,TRUE);
1028                         return 1;
1029                 }
1030
1031                 dev=linphone_core_get_sound_devices(lc);
1032                 index=atoi(arg2); /* FIXME: handle not-a-number */
1033                 for(i=0;dev[i]!=NULL;i++)
1034                 {
1035                         if (i!=index) continue;
1036
1037                         linphone_core_set_ringer_device(lc,dev[i]);
1038                         linphone_core_set_playback_device(lc,dev[i]);
1039                         linphone_core_set_capture_device(lc,dev[i]);
1040                         linphonec_out("Using sound device %s\n",dev[i]);
1041                         return 1;
1042                 }
1043                 linphonec_out("No such sound device\n");
1044                 return 1;
1045         }
1046         if (strcmp(arg1, "capture")==0)
1047         {
1048                 const char *devname=linphone_core_get_capture_device(lc);
1049                 if (!arg2){
1050                         linphonec_out("Using capture device #%i (%s)\n",
1051                                         devname_to_index(lc,devname),devname);
1052                 }else{
1053                         index=atoi(arg2); /* FIXME: handle not-a-number */
1054                         devname=index_to_devname(lc,index);
1055                         if (devname!=NULL){
1056                                 linphone_core_set_capture_device(lc,devname);
1057                                 linphonec_out("Using capture sound device %s\n",devname);
1058                                 return 1;
1059                         }
1060                         linphonec_out("No such sound device\n");
1061                 }
1062                 return 1;
1063         }
1064         if (strcmp(arg1, "playback")==0)
1065         {
1066                 const char *devname=linphone_core_get_playback_device(lc);
1067                 if (!arg2){
1068                         linphonec_out("Using playback device #%i (%s)\n",
1069                                         devname_to_index(lc,devname),devname);
1070                 }else{
1071                         index=atoi(arg2); /* FIXME: handle not-a-number */
1072                         devname=index_to_devname(lc,index);
1073                         if (devname!=NULL){
1074                                 linphone_core_set_playback_device(lc,devname);
1075                                 linphonec_out("Using playback sound device %s\n",devname);
1076                                 return 1;
1077                         }
1078                         linphonec_out("No such sound device\n");
1079                 }
1080                 return 1;
1081         }
1082         if (strcmp(arg1, "ring")==0)
1083         {
1084                 const char *devname=linphone_core_get_ringer_device(lc);
1085                 if (!arg2){
1086                         linphonec_out("Using ring device #%i (%s)\n",
1087                                         devname_to_index(lc,devname),devname);
1088                 }else{
1089                         index=atoi(arg2); /* FIXME: handle not-a-number */
1090                         devname=index_to_devname(lc,index);
1091                         if (devname!=NULL){
1092                                 linphone_core_set_ringer_device(lc,devname);
1093                                 linphonec_out("Using ring sound device %s\n",devname);
1094                                 return 1;
1095                         }
1096                         linphonec_out("No such sound device\n");
1097                 }
1098                 return 1;
1099         }
1100         return 0; /* syntax error */
1101 }
1102
1103 static int lpc_cmd_webcam(LinphoneCore *lc, char *args)
1104 {
1105         int i, index;
1106         const char **dev;
1107         char *arg1 = args;
1108         char *arg2 = NULL;
1109         char *ptr = args;
1110
1111         if (!args) return 0; /* syntax error */
1112
1113         /* Isolate first and second arg */
1114         while(*ptr && !isspace(*ptr)) ++ptr;
1115         if ( *ptr )
1116         {
1117                 *ptr='\0';
1118                 arg2=ptr+1;
1119                 while(*arg2 && isspace(*arg2)) ++arg2;
1120         }
1121
1122         if (strcmp(arg1, "list")==0)
1123         {
1124                 dev=linphone_core_get_video_devices(lc);
1125                 for(i=0; dev[i]!=NULL; ++i){
1126                         linphonec_out("%i: %s\n",i,dev[i]);
1127                 }
1128                 return 1;
1129         }
1130
1131         if (strcmp(arg1, "use")==0 && arg2)
1132         {
1133                 dev=linphone_core_get_video_devices(lc);
1134                 index=atoi(arg2); /* FIXME: handle not-a-number */
1135                 for(i=0;dev[i]!=NULL;i++)
1136                 {
1137                         if (i!=index) continue;
1138
1139                         linphone_core_set_video_device(lc, dev[i]);
1140                         linphonec_out("Using video device %s\n",dev[i]);
1141                         return 1;
1142                 }
1143                 linphonec_out("No such video device\n");
1144                 return 1;
1145         }
1146         return 0; /* syntax error */
1147 }
1148
1149 static int
1150 lpc_cmd_staticpic(LinphoneCore *lc, char *args)
1151 {
1152         char *arg1 = args;
1153         char *arg2 = NULL;
1154         char *ptr = args;
1155
1156         if (!args) return 0;  /* Syntax error */
1157
1158         /* Isolate first and second arg */
1159         while(*ptr && !isspace(*ptr)) ++ptr;
1160         if ( *ptr )
1161         {
1162                 *ptr='\0';
1163                 arg2=ptr+1;
1164                 while(*arg2 && isspace(*arg2)) ++arg2;
1165         }
1166
1167         if (strcmp(arg1, "set")==0 && arg2) {
1168                 linphone_core_set_static_picture(lc, arg2);
1169                 return 1;
1170         }
1171
1172         return 0; /* Syntax error */
1173 }
1174
1175 static int lpc_cmd_pause(LinphoneCore *lc, char *args){
1176
1177         if(linphone_core_in_call(lc))
1178         {
1179                 linphone_core_pause_call(lc,linphone_core_get_current_call(lc));
1180                 return 1;
1181         }
1182         linphonec_out("you can only pause when a call is in process\n");
1183     return 0;
1184 }
1185
1186 static int lpc_cmd_resume(LinphoneCore *lc, char *args){
1187         
1188         if(linphone_core_in_call(lc))
1189         {
1190                 linphonec_out("There is already a call in process pause or stop it first");
1191         }
1192         if (args)
1193         {
1194                 char the_remote_address[255];
1195                 int n = sscanf(args, "%s", the_remote_address);
1196                 if (n == 1)
1197                 {
1198                         if(linphone_core_resume_call(lc,linphone_core_get_call_by_remote_address(lc,the_remote_address)) < 0)
1199                         {
1200                                 linphonec_out("There was a problem to resume the call check the remote address you gave %s\n",args);
1201                                 return 0;
1202                         }
1203                         else
1204                         {
1205                                 return 1;
1206                         }
1207                 }
1208         }
1209         else
1210         {
1211                 int returned = 0;
1212                 MSList *calls = linphone_core_get_calls(lc);
1213                 if(ms_list_size(calls) == 1)
1214                 {
1215                         if(linphone_core_resume_call(lc,calls->data) < 0)
1216                         {
1217                                 linphonec_out("There was a problem to resume the unique call \n");
1218                                 returned = 0;
1219                         }
1220                         else
1221                         {
1222                                 returned = 1;
1223                         }
1224                         ms_list_free(calls);
1225                         return returned;
1226                 }
1227         }
1228         return 0;
1229     
1230 }
1231
1232 /***************************************************************************
1233  *
1234  *  Commands helper functions
1235  *
1236  ***************************************************************************/
1237
1238
1239 static void
1240 linphonec_proxy_add(LinphoneCore *lc)
1241 {
1242         bool_t enable_register=FALSE;
1243         LinphoneProxyConfig *cfg;
1244
1245         linphonec_out("Adding new proxy setup. Hit ^D to abort.\n");
1246
1247         /*
1248          * SIP Proxy address
1249          */
1250         while (1)
1251         {
1252                 char *input=linphonec_readline("Enter proxy sip address: ");
1253                 char *clean;
1254
1255                 if ( ! input ) {
1256                         linphonec_out("Aborted.\n");
1257                         return;
1258                 }
1259
1260                 /* Strip blanks */
1261                 clean=lpc_strip_blanks(input);
1262                 if ( ! *clean ) {
1263                         free(input);
1264                         continue;
1265                 }
1266
1267                 cfg=linphone_proxy_config_new();
1268                 if (linphone_proxy_config_set_server_addr(cfg,clean)<0)
1269                 {
1270                         linphonec_out("Invalid sip address (sip:sip.domain.tld).\n");
1271                         free(input);
1272                         linphone_proxy_config_destroy(cfg);
1273                         continue;
1274                 }
1275                 free(input);
1276                 break;
1277         }
1278
1279         /*
1280          * SIP Proxy identity
1281          */
1282         while (1)
1283         {
1284                 char *input=linphonec_readline("Your identity for this proxy: ");
1285                 char *clean;
1286
1287                 if ( ! input ) {
1288                         linphonec_out("Aborted.\n");
1289                         linphone_proxy_config_destroy(cfg);
1290                         return;
1291                 }
1292
1293                 /* Strip blanks */
1294                 clean=lpc_strip_blanks(input);
1295                 if ( ! *clean ) {
1296                         free(input);
1297                         continue;
1298                 }
1299
1300                 linphone_proxy_config_set_identity(cfg, clean);
1301                 if ( ! cfg->reg_identity )
1302                 {
1303                         linphonec_out("Invalid identity (sip:name@sip.domain.tld).\n");
1304                         free(input);
1305                         continue;
1306                 }
1307                 free(input);
1308                 break;
1309         }
1310
1311         /*
1312          * SIP Proxy enable register
1313          */
1314         while (1)
1315         {
1316                 char *input=linphonec_readline("Do you want to register on this proxy (yes/no): ");
1317                 char *clean;
1318
1319                 if ( ! input ) {
1320                         linphonec_out("Aborted.\n");
1321                         linphone_proxy_config_destroy(cfg);
1322                         return;
1323                 }
1324
1325                 /* Strip blanks */
1326                 clean=lpc_strip_blanks(input);
1327                 if ( ! *clean ) {
1328                         free(input);
1329                         continue;
1330                 }
1331
1332                 if ( ! strcmp(clean, "yes") ) enable_register=TRUE;
1333                 else if ( ! strcmp(clean, "no") ) enable_register=FALSE;
1334                 else {
1335                         linphonec_out("Please answer with 'yes' or 'no'\n");
1336                         free(input);
1337                         continue;
1338                 }
1339                 linphone_proxy_config_enableregister(cfg, enable_register);
1340                 free(input);
1341                 break;
1342         }
1343
1344         /*
1345          * SIP Proxy registration expiration
1346          */
1347         if ( enable_register==TRUE )
1348         {
1349                 long int expires=0;
1350                 while (1)
1351                 {
1352                         char *input=linphonec_readline("Specify register expiration time"
1353                                 " in seconds (default is 600): ");
1354
1355                         if ( ! input ) {
1356                                 linphonec_out("Aborted.\n");
1357                                 linphone_proxy_config_destroy(cfg);
1358                                 return;
1359                         }
1360
1361                         expires=strtol(input, (char **)NULL, 10);
1362                         if ( expires == LONG_MIN || expires == LONG_MAX )
1363                         {
1364                                 linphonec_out("Invalid value: %s\n", strerror(errno));
1365                                 free(input);
1366                                 continue;
1367                         }
1368
1369                         linphone_proxy_config_expires(cfg, expires);
1370                         linphonec_out("Expiration: %d seconds\n", cfg->expires);
1371
1372                         free(input);
1373                         break;
1374                 }
1375         }
1376
1377         /*
1378          * SIP proxy route
1379          */
1380         while (1)
1381         {
1382                 char *input=linphonec_readline("Specify route if needed: ");
1383                 char *clean;
1384
1385                 if ( ! input ) {
1386                         linphonec_out("Aborted.\n");
1387                         linphone_proxy_config_destroy(cfg);
1388                         return;
1389                 }
1390
1391                 /* Strip blanks */
1392                 clean=lpc_strip_blanks(input);
1393                 if ( ! *clean ) {
1394                         free(input);
1395                         linphonec_out("No route specified.\n");
1396                         break;
1397                 }
1398
1399                 linphone_proxy_config_set_route(cfg, clean);
1400                 if ( ! cfg->reg_route )
1401                 {
1402                         linphonec_out("Invalid route.\n");
1403                         free(input);
1404                         continue;
1405                 }
1406
1407                 free(input);
1408                 break;
1409         }
1410
1411         /*
1412          * Final confirmation 
1413          */
1414         while (1)
1415         {
1416                 char *input;
1417                 char *clean;
1418
1419                 linphonec_out("--------------------------------------------\n");
1420                 linphonec_proxy_display(cfg);
1421                 linphonec_out("--------------------------------------------\n");
1422                 input=linphonec_readline("Accept the above proxy configuration (yes/no) ?: ");
1423
1424
1425                 if ( ! input ) {
1426                         linphonec_out("Aborted.\n");
1427                         linphone_proxy_config_destroy(cfg);
1428                         return;
1429                 }
1430
1431                 /* Strip blanks */
1432                 clean=lpc_strip_blanks(input);
1433                 if ( ! *clean ) {
1434                         free(input);
1435                         continue;
1436                 }
1437
1438                 if ( ! strcmp(clean, "yes") ) break;
1439                 else if ( ! strcmp(clean, "no") )
1440                 {
1441                         linphonec_out("Declined.\n");
1442                         linphone_proxy_config_destroy(cfg);
1443                         free(input);
1444                         return;
1445                 }
1446
1447                 linphonec_out("Please answer with 'yes' or 'no'\n");
1448                 free(input);
1449                 continue;
1450         }
1451
1452
1453         linphone_core_add_proxy_config(lc,cfg);
1454
1455         /* automatically set the last entered proxy as the default one */
1456         linphone_core_set_default_proxy(lc,cfg);
1457
1458         linphonec_out("Proxy added.\n");
1459 }
1460
1461 static void
1462 linphonec_proxy_display(LinphoneProxyConfig *cfg)
1463 {
1464         linphonec_out("sip address: %s\nroute: %s\nidentity: %s\nregister: %s\nexpires: %i\nregistered: %s\n",
1465                         cfg->reg_proxy,
1466                         (cfg->reg_route!=NULL)?cfg->reg_route:"",
1467                         (cfg->reg_identity!=NULL)?cfg->reg_identity:"",
1468                         (cfg->reg_sendregister)?"yes":"no",
1469                         cfg->expires,
1470                         linphone_proxy_config_is_registered(cfg) ? "yes" : "no");
1471 }
1472
1473 static void linphonec_proxy_show(LinphoneCore *lc, int index)
1474 {
1475         const MSList *elem;
1476         int i;
1477         for(elem=linphone_core_get_proxy_config_list(lc),i=0;elem!=NULL;elem=elem->next,++i){
1478                 if (index==i){
1479                         LinphoneProxyConfig *cfg=(LinphoneProxyConfig *)elem->data;
1480                         linphonec_proxy_display(cfg);
1481                         return;
1482                 }
1483         }
1484         linphonec_out("No proxy with index %i\n", index);
1485 }
1486
1487 static void
1488 linphonec_proxy_list(LinphoneCore *lc)
1489 {
1490         const MSList *proxies;
1491         int n;
1492         int def=linphone_core_get_default_proxy(lc,NULL);
1493         
1494         proxies=linphone_core_get_proxy_config_list(lc);
1495         for(n=0;proxies!=NULL;proxies=ms_list_next(proxies),n++){
1496                 if (n==def)
1497                         linphonec_out("****** Proxy %i - this is the default one - *******\n",n);
1498                 else 
1499                         linphonec_out("****** Proxy %i *******\n",n);
1500                 linphonec_proxy_display((LinphoneProxyConfig*)proxies->data);
1501         }
1502         if ( ! n ) linphonec_out("No proxies defined\n");
1503 }
1504
1505 static void
1506 linphonec_proxy_remove(LinphoneCore *lc, int index)
1507 {
1508         const MSList *proxies;
1509         LinphoneProxyConfig *cfg;
1510         proxies=linphone_core_get_proxy_config_list(lc);
1511         cfg=(LinphoneProxyConfig*)ms_list_nth_data(proxies,index);
1512         if (cfg==NULL){
1513                 linphonec_out("No such proxy.\n");
1514                 return;
1515         }
1516         linphone_core_remove_proxy_config(lc,cfg);
1517         linphonec_out("Proxy %s removed.\n", cfg->reg_proxy);
1518         linphone_proxy_config_destroy(cfg);
1519 }
1520
1521 static int
1522 linphonec_proxy_use(LinphoneCore *lc, int index)
1523 {
1524         const MSList *proxies;
1525         LinphoneProxyConfig *cfg;
1526         proxies=linphone_core_get_proxy_config_list(lc);
1527         cfg=(LinphoneProxyConfig*)ms_list_nth_data(proxies,index);
1528         if (cfg==NULL){
1529                 linphonec_out("No such proxy (try 'proxy list').");
1530                 return 0;
1531         }
1532         linphone_core_set_default_proxy(lc,cfg);
1533         return 1;
1534 }
1535
1536 static void
1537 linphonec_friend_display(LinphoneFriend *fr)
1538 {
1539         LinphoneAddress *uri=linphone_address_clone(linphone_friend_get_address(fr));
1540         char *str;
1541         
1542         linphonec_out("name: %s\n", linphone_address_get_display_name(uri));
1543         linphone_address_set_display_name(uri,NULL);
1544         str=linphone_address_as_string(uri);
1545         linphonec_out("address: %s\n", str);
1546 }
1547
1548 static int
1549 linphonec_friend_list(LinphoneCore *lc, char *pat)
1550 {
1551         const MSList *friend;
1552         int n;
1553
1554         if (pat) {
1555                 pat=lpc_strip_blanks(pat);
1556                 if (!*pat) pat = NULL;
1557         }
1558
1559         friend = linphone_core_get_friend_list(lc);
1560         for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1561         {
1562                 if ( pat ) {
1563                         const char *name = linphone_address_get_display_name(
1564                             linphone_friend_get_address((LinphoneFriend*)friend->data));
1565                         if (name && ! strstr(name, pat) ) continue;
1566                 }
1567                 linphonec_out("****** Friend %i *******\n",n);
1568                 linphonec_friend_display((LinphoneFriend*)friend->data);
1569         }
1570
1571         return 1;
1572 }
1573
1574 static int
1575 linphonec_friend_call(LinphoneCore *lc, unsigned int num)
1576 {
1577         const MSList *friend = linphone_core_get_friend_list(lc);
1578         unsigned int n;
1579         char *addr;
1580
1581         for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1582         {
1583                 if ( n == num )
1584                 {
1585                         int ret;
1586                         addr = linphone_address_as_string(linphone_friend_get_address((LinphoneFriend*)friend->data));
1587                         ret=lpc_cmd_call(lc, addr);
1588                         ms_free(addr);
1589                         return ret;
1590                 }
1591         }
1592         linphonec_out("No such friend %u\n", num);
1593         return 1;
1594 }
1595
1596 #ifndef WIN32
1597 static int
1598 linphonec_friend_add(LinphoneCore *lc, const char *name, const char *addr)
1599 {
1600         LinphoneFriend *newFriend;
1601
1602         char url[PATH_MAX];
1603
1604         snprintf(url, PATH_MAX, "%s <%s>", name, addr);
1605         newFriend = linphone_friend_new_with_addr(url);
1606         linphone_core_add_friend(lc, newFriend);
1607         return 0;
1608 }
1609 #endif
1610
1611 static int
1612 linphonec_friend_delete(LinphoneCore *lc, int num)
1613 {
1614         const MSList *friend = linphone_core_get_friend_list(lc);
1615         unsigned int n;
1616
1617         for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1618         {
1619                 if ( n == num )
1620                 {
1621                         linphone_core_remove_friend(lc, friend->data);
1622                         return 0;
1623                 }
1624         }
1625
1626         if (-1 == num) 
1627         {
1628                 unsigned int i;
1629                 for (i = 0 ; i < n ; i++)
1630                         linphonec_friend_delete(lc, 0);
1631                 return 0;
1632         }
1633
1634         linphonec_out("No such friend %u\n", num);
1635         return 1;
1636 }
1637
1638 static void
1639 linphonec_display_command_help(LPC_COMMAND *cmd)
1640 {
1641         if ( cmd->doc ) linphonec_out ("%s\n", cmd->doc);
1642         else linphonec_out("%s\n", cmd->help);
1643 }
1644
1645
1646 static int lpc_cmd_register(LinphoneCore *lc, char *args){
1647         char identity[512];
1648         char proxy[512];
1649         char passwd[512];
1650         LinphoneProxyConfig *cfg;
1651         const MSList *elem;
1652     
1653         if (!args)
1654         {
1655                 /* it means that you want to register the default proxy */
1656                 LinphoneProxyConfig *cfg=NULL;
1657                 linphone_core_get_default_proxy(lc,&cfg);
1658                 if (cfg)
1659                 {
1660                         if(!linphone_proxy_config_is_registered(cfg)) {
1661                                 linphone_proxy_config_enable_register(cfg,TRUE);
1662                                 linphone_proxy_config_done(cfg);
1663                         }else{
1664                                 linphonec_out("default proxy already registered\n");
1665                         }
1666                 }else{
1667                         linphonec_out("we do not have a default proxy\n");
1668                         return 0;
1669                 }
1670                 return 1;
1671         }
1672         passwd[0]=proxy[0]=identity[0]='\0';
1673         sscanf(args,"%s %s %s",identity,proxy,passwd);
1674         if (proxy[0]=='\0' || identity[0]=='\0'){
1675                 linphonec_out("Missing parameters, see help register\n");
1676                 return 1;
1677         }
1678         if (passwd[0]!='\0'){
1679                 LinphoneAddress *from;
1680                 LinphoneAuthInfo *info;
1681                 if ((from=linphone_address_new(identity))!=NULL){
1682                         char realm[128];
1683                         snprintf(realm,sizeof(realm)-1,"\"%s\"",linphone_address_get_domain(from));
1684                         info=linphone_auth_info_new(linphone_address_get_username(from),NULL,passwd,NULL,NULL);
1685                         linphone_core_add_auth_info(lc,info);
1686                         linphone_address_destroy(from);
1687                         linphone_auth_info_destroy(info);
1688                 }
1689         }
1690         elem=linphone_core_get_proxy_config_list(lc);
1691         if (elem) {
1692                 cfg=(LinphoneProxyConfig*)elem->data;
1693                 linphone_proxy_config_edit(cfg);
1694         }
1695         else cfg=linphone_proxy_config_new();
1696         linphone_proxy_config_set_identity(cfg,identity);
1697         linphone_proxy_config_set_server_addr(cfg,proxy);
1698         linphone_proxy_config_enable_register(cfg,TRUE);
1699         if (elem) linphone_proxy_config_done(cfg);
1700         else linphone_core_add_proxy_config(lc,cfg);
1701         linphone_core_set_default_proxy(lc,cfg);
1702         return 1;
1703 }
1704
1705 static int lpc_cmd_unregister(LinphoneCore *lc, char *args){
1706         LinphoneProxyConfig *cfg=NULL;
1707         linphone_core_get_default_proxy(lc,&cfg);
1708         if (cfg && linphone_proxy_config_is_registered(cfg)) {
1709                 linphone_proxy_config_edit(cfg);
1710                 linphone_proxy_config_enable_register(cfg,FALSE);
1711                 linphone_proxy_config_done(cfg);
1712         }else{
1713                 linphonec_out("unregistered\n");
1714         }
1715         return 1;
1716 }
1717
1718 static int lpc_cmd_duration(LinphoneCore *lc, char *args){
1719         LinphoneCallLog *cl;
1720         const MSList *elem=linphone_core_get_call_logs(lc);
1721         for(;elem!=NULL;elem=elem->next){
1722                 if (elem->next==NULL){
1723                         cl=(LinphoneCallLog*)elem->data;
1724                         linphonec_out("%i seconds\n",cl->duration);
1725                 }
1726         }
1727         return 1;
1728 }
1729
1730 static int lpc_cmd_status(LinphoneCore *lc, char *args)
1731 {
1732         LinphoneProxyConfig *cfg;
1733         
1734         if ( ! args ) return 0;
1735         linphone_core_get_default_proxy(lc,&cfg);
1736         if (strstr(args,"register"))
1737         {
1738                 if (cfg)
1739                 {
1740                         if (linphone_proxy_config_is_registered(cfg)){
1741                                 linphonec_out("registered, identity=%s duration=%i\n",
1742                                         linphone_proxy_config_get_identity(cfg),
1743                                         linphone_proxy_config_get_expires(cfg));
1744                         }else if (linphone_proxy_config_register_enabled(cfg)){
1745                                 linphonec_out("registered=-1\n");
1746                         }else linphonec_out("registered=0\n");
1747                 }
1748                 else linphonec_out("registered=0\n");
1749         }
1750         else if (strstr(args,"autoanswer"))
1751         {
1752                 if (cfg && linphone_proxy_config_is_registered(cfg))
1753                         linphonec_out("autoanswer=%i\n",linphonec_get_autoanswer());
1754                 else linphonec_out("unregistered\n");
1755         }
1756         else if (strstr(args,"hook"))
1757         {
1758                 gstate_t call_state=linphone_core_get_state(lc,GSTATE_GROUP_CALL);
1759 /*
1760                 if (!cfg || !linphone_proxy_config_is_registered(cfg)){
1761                         linphonec_out("unregistered\n");
1762                         return 1;
1763                 }
1764  */
1765                 switch(call_state){
1766                         case GSTATE_CALL_OUT_INVITE:
1767                                 linphonec_out("hook=dialing\n");
1768                         break;
1769                         case GSTATE_CALL_IDLE:
1770                                 linphonec_out("hook=offhook\n");
1771                         break;
1772                         case GSTATE_CALL_OUT_CONNECTED:
1773                                 linphonec_out("Call out, hook=%s duration=%i\n", linphonec_get_callee(),
1774                                         linphone_core_get_current_call_duration(lc));
1775                         break;
1776                         case GSTATE_CALL_IN_CONNECTED:
1777                                 linphonec_out("hook=answered duration=%i\n" ,
1778                                         linphone_core_get_current_call_duration(lc));
1779                                 break;
1780                         case GSTATE_CALL_IN_INVITE:
1781                                 linphonec_out("Incoming call from %s\n",linphonec_get_caller());
1782                                 break;
1783                         default:
1784                                 break;
1785                 }
1786                 
1787         }
1788         else return 0;
1789
1790         return 1;
1791 }
1792
1793 static int lpc_cmd_ports(LinphoneCore *lc, char *args)
1794 {
1795         int port;
1796         if ( ! args ){
1797                 linphonec_out("sip port = %i\naudio rtp port = %i\nvideo rtp port = %i\n",
1798                         linphone_core_get_sip_port(lc),
1799                         linphone_core_get_audio_port(lc),
1800                         linphone_core_get_video_port(lc));
1801                 return 1;
1802         }
1803         if (sscanf(args,"sip %i",&port)==1){
1804                 linphonec_out("Setting sip port to %i\n",port);
1805                 linphone_core_set_sip_port(lc,port);
1806         }else return 0;
1807
1808         return 1;
1809 }
1810
1811 static int lpc_cmd_speak(LinphoneCore *lc, char *args){
1812 #ifndef WIN32
1813         char voice[64];
1814         char *sentence;
1815         char cl[128];
1816         char *wavfile;
1817         int status;
1818         FILE *file;
1819         
1820     if (!args) return 0;
1821         memset(voice,0,sizeof(voice));
1822         sscanf(args,"%s63",voice);
1823         sentence=args+strlen(voice);
1824         wavfile=tempnam("/tmp/","linphonec-espeak-");
1825         snprintf(cl,sizeof(cl),"espeak -v %s -s 100 -w %s --stdin",voice,wavfile);
1826         file=popen(cl,"w");
1827         if (file==NULL){
1828                 ms_error("Could not open pipe to espeak !");
1829                 return 1;
1830         }
1831         fprintf(file,"%s",sentence);
1832         status=pclose(file);
1833         if (WEXITSTATUS(status)==0){
1834                 linphone_core_set_play_file(lc,wavfile);
1835         }else{
1836                 linphonec_out("espeak command failed.");
1837         }
1838 #else
1839         linphonec_out("Sorry, this command is not implemented in windows version.");
1840 #endif
1841         return 1;
1842 }
1843
1844 static int lpc_cmd_codec(LinphoneCore *lc, char *args){
1845         char *arg1 = args;
1846         char *arg2 = NULL;
1847         char *ptr = args;
1848
1849         if (!args) return 0;
1850
1851         /* Isolate first and second arg */
1852         while(*ptr && !isspace(*ptr)) ++ptr;
1853         if ( *ptr )
1854         {
1855                 *ptr='\0';
1856                 arg2=ptr+1;
1857                 while(*arg2 && isspace(*arg2)) ++arg2;
1858         }
1859
1860         if (strcmp(arg1,"enable")==0)
1861         {
1862 #ifdef HAVE_READLINE
1863                 rl_inhibit_completion=1;
1864 #endif
1865         if (!strcmp(arg2,"all")) linphonec_codec_enable(lc,-1);
1866         else linphonec_codec_enable(lc,atoi(arg2));
1867 #ifdef HAVE_READLINE
1868                 rl_inhibit_completion=0;
1869 #endif
1870         }
1871         else if (strcmp(arg1,"list")==0)
1872         {
1873                 linphonec_codec_list(lc);
1874         }
1875         else if (strcmp(arg1,"disable")==0)
1876         {
1877         if (!strcmp(arg2,"all")) linphonec_codec_disable(lc,-1);
1878         else linphonec_codec_disable(lc,atoi(arg2));
1879         }
1880         else
1881         {
1882                 return 0; /* syntax error */
1883         }
1884
1885         return 1;
1886 }
1887
1888 static void linphonec_codec_list(LinphoneCore *lc){
1889         PayloadType *pt;
1890     codecs_config_t *config=&lc->codecs_conf;
1891         int index=0;
1892         MSList *node;
1893         for(node=config->audio_codecs;node!=NULL;node=ms_list_next(node)){
1894                 pt=(PayloadType*)(node->data);
1895         linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, 
1896                     linphone_core_payload_type_enabled(lc,pt) ? "enabled" : "disabled");
1897                 index++;
1898         }
1899 }
1900
1901 static void linphonec_codec_enable(LinphoneCore *lc, int sel_index){
1902         PayloadType *pt;
1903     codecs_config_t *config=&lc->codecs_conf;
1904         int index=0;
1905         MSList *node;
1906     for(node=config->audio_codecs;node!=NULL;node=ms_list_next(node)){
1907         if (index == sel_index || sel_index == -1) {
1908                     pt=(PayloadType*)(node->data);
1909             pt->flags|=PAYLOAD_TYPE_ENABLED;
1910             linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, "enabled");
1911         }
1912                 index++;
1913         }
1914 }
1915
1916 static void linphonec_codec_disable(LinphoneCore *lc, int sel_index){
1917         PayloadType *pt;
1918     codecs_config_t *config=&lc->codecs_conf;
1919         int index=0;
1920         MSList *node;
1921         for(node=config->audio_codecs;node!=NULL;node=ms_list_next(node)){
1922         if (index == sel_index || sel_index == -1) {
1923                 pt=(PayloadType*)(node->data);
1924             pt->flags&=~PAYLOAD_TYPE_ENABLED;
1925             linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, "disabled");
1926         }
1927                 index++;
1928         }
1929 }
1930
1931 static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args){
1932         char *arg1 = args;
1933         char *arg2 = NULL;
1934         char *ptr = args;
1935
1936         if (!args) return 0;
1937
1938         /* Isolate first and second arg */
1939         while(*ptr && !isspace(*ptr)) ++ptr;
1940         if ( *ptr )
1941         {
1942                 *ptr='\0';
1943                 arg2=ptr+1;
1944                 while(*arg2 && isspace(*arg2)) ++arg2;
1945         }
1946
1947         if (strcmp(arg1,"on")==0){
1948         int delay, tail_len, frame_size;
1949         int n;
1950
1951         linphone_core_enable_echo_cancellation(lc,1);
1952
1953         if (arg2 != 0) {
1954             n = sscanf(arg2, "%d %d %d", &delay, &tail_len, &frame_size);
1955
1956             if (n == 1) {   
1957                 lp_config_set_int(lc->config,"sound","ec_delay",delay);
1958             }
1959             else if (n == 2) {
1960                 lp_config_set_int(lc->config,"sound","ec_delay",delay);
1961                 lp_config_set_int(lc->config,"sound","ec_tail_len",tail_len);
1962             }
1963             else if (n == 3) {
1964                 lp_config_set_int(lc->config,"sound","ec_delay",delay);
1965                 lp_config_set_int(lc->config,"sound","ec_tail_len",tail_len);
1966                 lp_config_set_int(lc->config,"sound","ec_framesize",frame_size);
1967             }
1968         }
1969     }
1970     else if (strcmp(arg1,"off")==0){
1971         linphone_core_enable_echo_cancellation(lc,0);
1972     }
1973     else if (strcmp(arg1,"show")==0){
1974         linphonec_out("echo cancellation is %s; delay %d, tail length %d, frame size %d\n", 
1975             linphone_core_echo_cancellation_enabled(lc) ? "on" : "off",
1976             lp_config_get_int(lc->config,"sound","ec_delay",0),
1977             lp_config_get_int(lc->config,"sound","ec_tail_len",0),
1978             lp_config_get_int(lc->config,"sound","ec_framesize",0));        
1979     }
1980     else {
1981         return 0;
1982     }
1983
1984     return 1;
1985 }
1986
1987 /***************************************************************************
1988  *
1989  *  Command table management funx
1990  *
1991  ***************************************************************************/
1992
1993 /*
1994  * Find a command given its name
1995  */
1996 static LPC_COMMAND *
1997 lpc_find_command(const char *name)
1998 {
1999         int i;
2000
2001         for (i=0; commands[i].name; ++i)
2002         {
2003                 if (strcmp(name, commands[i].name) == 0)
2004                         return &commands[i];
2005         }
2006
2007         return (LPC_COMMAND *)NULL;
2008 }
2009
2010
2011 /****************************************************************************
2012  *
2013  * $Log: commands.c,v $
2014  * Revision 1.39  2008/07/03 15:08:34  smorlat
2015  * api cleanups, interface in progress.
2016  *
2017  * Revision 1.38  2008/06/17 20:38:59  smorlat
2018  * added missing file.
2019  *
2020  * Revision 1.37  2008/04/09 09:26:00  smorlat
2021  * merge various patches
2022  * H264 support.
2023  *
2024  * Revision 1.36  2007/08/01 14:47:53  strk
2025  *         * console/commands.c: Clean up commands 'nat', 'stun'
2026  *           and 'firewall' to be more intuitive.
2027  *
2028  * Revision 1.35  2007/06/27 09:01:25  smorlat
2029  * logging improvements.
2030  *
2031  * Revision 1.34  2007/02/20 10:17:13  smorlat
2032  * linphonec friends patch2
2033  *
2034  * Revision 1.31  2006/09/22 07:22:47  smorlat
2035  * linphonecore api changes.
2036  *
2037  * Revision 1.30  2006/09/08 15:32:57  smorlat
2038  * support for using files instead of soundcard (used by linphonec only)
2039  *
2040  * Revision 1.29  2006/08/28 14:29:07  smorlat
2041  * fix bug.
2042  *
2043  * Revision 1.28  2006/08/21 12:49:59  smorlat
2044  * merged several little patches.
2045  *
2046  * Revision 1.27  2006/07/17 18:45:00  smorlat
2047  * support for several event queues in ortp.
2048  * glib dependency removed from coreapi/ and console/
2049  *
2050  * Revision 1.26  2006/04/14 15:16:36  smorlat
2051  * soundcard use did nothing !
2052  *
2053  * Revision 1.25  2006/04/06 20:09:33  smorlat
2054  * add linphonec command to see and select sound devices.
2055  *
2056  * Revision 1.24  2006/03/04 11:17:10  smorlat
2057  * mediastreamer2 in progress.
2058  *
2059  * Revision 1.23  2006/02/20 21:14:01  strk
2060  * Handled syntax errors with 'friend' command
2061  *
2062  * Revision 1.22  2006/02/20 10:20:29  strk
2063  * Added substring-based filter support for command 'friend list'
2064  *
2065  * Revision 1.21  2006/02/02 15:39:18  strk
2066  * - Added 'friend list' and 'friend call' commands
2067  * - Allowed for multiple DTFM send in a single line
2068  * - Added status-specific callback (bare version)
2069  *
2070  * Revision 1.20  2006/01/26 11:54:34  strk
2071  * More robust 'nat' command handler (strip blanks in args)
2072  *
2073  * Revision 1.19  2006/01/26 09:48:05  strk
2074  * Added limits.h include
2075  *
2076  * Revision 1.18  2006/01/26 02:18:05  strk
2077  * Added new commands 'nat use' and 'nat unuse'.
2078  * These will required a pending patch to linphonecore.c
2079  * in order to work.
2080  *
2081  * Revision 1.17  2006/01/20 14:12:33  strk
2082  * Added linphonec_init() and linphonec_finish() functions.
2083  * Handled SIGINT and SIGTERM to invoke linphonec_finish().
2084  * Handling of auto-termination (-t) moved to linphonec_finish().
2085  * Reworked main (input read) loop to not rely on 'terminate'
2086  * and 'run' variable (dropped). configfile_name allocated on stack
2087  * using PATH_MAX limit. Changed print_usage signature to allow
2088  * for an exit_status specification.
2089  *
2090  * Revision 1.16  2006/01/18 09:25:32  strk
2091  * Command completion inhibited in proxy addition and auth request prompts.
2092  * Avoided use of linphonec_readline's internal filename completion.
2093  *
2094  * Revision 1.15  2006/01/14 13:29:32  strk
2095  * Reworked commands interface to use a table structure,
2096  * used by command line parser and help function.
2097  * Implemented first level of completion (commands).
2098  * Added notification of invalid "answer" and "terminate"
2099  * commands (no incoming call, no active call).
2100  * Forbidden "call" intialization when a call is already active.
2101  * Cleaned up all commands, adding more feedback and error checks.
2102  *
2103  * Revision 1.14  2006/01/13 13:00:29  strk
2104  * Added linphonec.h. Code layout change (added comments, forward decl,
2105  * globals on top, copyright notices and Logs). Handled out-of-memory
2106  * condition on history management. Removed assumption on sizeof(char).
2107  * Fixed bug in authentication prompt (introduced by linphonec_readline).
2108  * Added support for multiple authentication requests (up to MAX_PENDING_AUTH).
2109  *
2110  *
2111  ****************************************************************************/