RTS API Documentation  1.10.11
switch_console.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  *
28  *
29  * switch_console.c -- Simple Console
30  *
31  */
32 
33 #include <switch.h>
34 #include <switch_console.h>
35 #ifndef _MSC_VER
36 #include <switch_private.h>
37 #endif
38 #define CMD_BUFLEN 1024
39 
40 #ifdef HAVE_LIBEDIT
41 #include <histedit.h>
42 
43 static EditLine *el;
44 static History *myhistory;
45 static HistEvent ev;
46 static char *hfile = NULL;
47 
48 #else
49 
50 #define CC_NORM 0
51 #define CC_NEWLINE 1
52 #define CC_EOF 2
53 #define CC_ARGHACK 3
54 #define CC_REFRESH 4
55 #define CC_CURSOR 5
56 #define CC_ERROR 6
57 #define CC_FATAL 7
58 #define CC_REDISPLAY 8
59 #define CC_REFRESH_BEEP 9
60 
61 #ifdef _MSC_VER
62 #define HISTLEN 10
63 #define KEY_UP 1
64 #define KEY_DOWN 2
65 #define KEY_TAB 3
66 #define CLEAR_OP 4
67 #define DELETE_REFRESH_OP 5
68 #define KEY_LEFT 6
69 #define KEY_RIGHT 7
70 #define KEY_INSERT 8
71 #define PROMPT_OP 9
72 #define KEY_DELETE 10
73 
74 static int console_bufferInput(char *buf, int len, char *cmd, int key);
75 #endif
76 #endif
77 
78 /*
79  * store a strdup() of the string configured in XML
80  * bound to each of the 12 function key
81  */
82 static char *console_fnkeys[12];
83 
84 /*
85  * Load from console.conf XML file the section:
86  * <keybindings>
87  * <key name="1" value="show calls"/>
88  * </keybindings>
89  */
91 {
92  char *cf = "switch.conf";
93  switch_xml_t cfg, xml, settings, param;
94 
95  /* clear the keybind array */
96  int i;
97 
98  for (i = 0; i < 12; i++) {
99  console_fnkeys[i] = NULL;
100  }
101 
102  if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
103  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
104  return SWITCH_STATUS_TERM;
105  }
106 
107  if ((settings = switch_xml_child(cfg, "cli-keybindings"))) {
108  for (param = switch_xml_child(settings, "key"); param; param = param->next) {
109  char *var = (char *) switch_xml_attr_soft(param, "name");
110  char *val = (char *) switch_xml_attr_soft(param, "value");
111  i = atoi(var);
112  if ((i < 1) || (i > 12)) {
113  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Keybind %s is invalid, range is from 1 to 12\n", var);
114  } else {
115  /* Add the command to the fnkey array */
117  }
118  }
119  }
120 
121  switch_xml_free(xml);
122 
123  return SWITCH_STATUS_SUCCESS;
124 }
125 
127 {
128  switch_size_t need = handle->data_len + datalen;
129 
130  if (need >= handle->data_size) {
131  void *new_data;
132  need += handle->alloc_chunk;
133 
134  if (!(new_data = realloc(handle->data, need))) {
135  return SWITCH_STATUS_MEMERR;
136  }
137 
138  handle->data = new_data;
139  handle->data_size = need;
140  }
141 
142  memcpy((uint8_t *) (handle->data) + handle->data_len, data, datalen);
143  handle->data_len += datalen;
144  handle->end = (uint8_t *) (handle->data) + handle->data_len;
145  *(uint8_t *) handle->end = '\0';
146 
147  return SWITCH_STATUS_SUCCESS;
148 }
149 
151 {
152  va_list ap;
153  char *end = handle->end;
154  int ret = 0;
155  char *data = NULL;
156 
157  if (handle->data_len >= handle->data_size) {
158  return SWITCH_STATUS_FALSE;
159  }
160 
161  va_start(ap, fmt);
162  //ret = switch_vasprintf(&data, fmt, ap);
163  if (!(data = switch_vmprintf(fmt, ap))) {
164  ret = -1;
165  }
166  va_end(ap);
167 
168  if (data) {
169  switch_size_t remaining = handle->data_size - handle->data_len;
170  switch_size_t need = strlen(data) + 1;
171 
172  if ((remaining < need) && handle->alloc_len) {
173  switch_size_t new_len;
174  void *new_data;
175 
176  new_len = handle->data_size + need + handle->alloc_chunk;
177  if ((new_data = realloc(handle->data, new_len))) {
178  handle->data_size = handle->alloc_len = new_len;
179  handle->data = new_data;
180  remaining = handle->data_size - handle->data_len;
181  handle->end = (uint8_t *) (handle->data) + handle->data_len;
182  end = handle->end;
183  } else {
185  free(data);
186  return SWITCH_STATUS_FALSE;
187  }
188  }
189 
190  if (remaining < need) {
191  ret = -1;
192  } else {
193  ret = 0;
194  switch_snprintf(end, remaining, "%s", data);
195  handle->data_len += strlen(data);
196  handle->end = (uint8_t *) (handle->data) + handle->data_len;
197  }
198  free(data);
199  }
200 
202 }
203 
205 {
206  char *dpath = NULL;
207  FILE *fd = NULL;
209 
210  if (!switch_is_file_path(path)) {
212  path = dpath;
213  }
214 
215  if ((fd = fopen(path, "r"))) {
216  char *line_buf = NULL;
217  switch_size_t llen = 0;
218 
219  while (switch_fp_read_dline(fd, &line_buf, &llen)) {
220  stream->write_function(stream, "%s", line_buf);
221  }
222  fclose(fd);
223  switch_safe_free(line_buf);
224  status = SWITCH_STATUS_SUCCESS;
225  }
226 
227  switch_safe_free(dpath);
228  return status;
229 }
230 
231 static int alias_callback(void *pArg, int argc, char **argv, char **columnNames)
232 {
233  char **r = (char **) pArg;
234  *r = strdup(argv[0]);
235  return -1;
236 }
237 
238 SWITCH_DECLARE(char *) switch_console_expand_alias(char *cmd, char *arg)
239 {
240  char *errmsg = NULL;
241  char *r = NULL;
242  char *sql = NULL;
243  char *exp = NULL;
244  switch_cache_db_handle_t *db = NULL;
246  int full = 0;
247 
248 
249  if (!(cflags & SCF_USE_SQL)) {
250  return NULL;
251  }
252 
255  return NULL;
256  }
257 
258 
260  sql = switch_mprintf("select command from aliases where alias='%q'", cmd);
261  } else {
262  sql = switch_mprintf("select command from aliases where alias='%w'", cmd);
263  }
264 
266 
267  if (errmsg) {
268  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error [%s][%s]\n", sql, errmsg);
269  free(errmsg);
270  }
271 
272  switch_safe_free(sql);
273 
274  if (!r) {
276  sql = switch_mprintf("select command from aliases where alias='%q %q'", cmd, arg);
277  } else {
278  sql = switch_mprintf("select command from aliases where alias='%w %w'", cmd, arg);
279  }
280 
282 
283  if (errmsg) {
284  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error [%s][%s]\n", sql, errmsg);
285  free(errmsg);
286  }
287  if (r) {
288  full++;
289  }
290  }
291 
292  switch_safe_free(sql);
293 
294  if (r) {
295  if (arg && !full) {
296  exp = switch_mprintf("%s %s", r, arg);
297  free(r);
298  } else {
299  exp = r;
300  }
301  } else {
302  exp = cmd;
303  }
304 
306 
307  return exp;
308 }
309 
310 
311 static int switch_console_process(char *xcmd)
312 {
313  switch_stream_handle_t stream = { 0 };
314  switch_status_t status;
315  FILE *handle = switch_core_get_console();
316  int r = 1;
317 
318  SWITCH_STANDARD_STREAM(stream);
319  switch_assert(stream.data);
320 
321  status = switch_console_execute(xcmd, 0, &stream);
322 
323  if (status == SWITCH_STATUS_SUCCESS) {
324  if (handle) {
325  fprintf(handle, "\n%s\n", (char *) stream.data);
326  fflush(handle);
327  }
328  } else {
329  if (!strcasecmp(xcmd, "...") || !strcasecmp(xcmd, "shutdown")) {
330  r = 0;
331  }
332  if (handle) {
333  fprintf(handle, "Unknown Command: %s\n", xcmd);
334  fflush(handle);
335  }
336  }
337 
338  switch_safe_free(stream.data);
339 
340  return r;
341 
342 }
343 
344 
346 {
347  char *arg = NULL, *alias = NULL;
348 
349  char *delim = ";;";
350  int argc;
351  char *argv[128];
352  int x;
353  char *dup = NULL;
354  char *cmd;
355 
357 
358 
359  if (rec > 100) {
360  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Too much recursion!\n");
361  goto end;
362  }
363 
364  while (*xcmd == ' ') xcmd++;
365 
366  dup = strdup(xcmd);
367 
368  if (!strncasecmp(xcmd, "alias", 5)) {
369  argc = 1;
370  argv[0] = xcmd;
371  } else {
372  argc = switch_separate_string_string(dup, delim, argv, 128);
373  }
374 
375  for (x = 0; x < argc; x++) {
376  cmd = argv[x];
377  if ((arg = strchr(cmd, '\r')) != 0 || (arg = strchr(cmd, '\n')) != 0) {
378  *arg = '\0';
379  arg = NULL;
380  }
381  if ((arg = strchr(cmd, ' ')) != 0) {
382  *arg++ = '\0';
383  }
384 
385  if ((alias = switch_console_expand_alias(cmd, arg)) && alias != cmd) {
386  istream->write_function(istream, "\nExpand Alias [%s]->[%s]\n\n", cmd, alias);
387  status = switch_console_execute(alias, ++rec, istream);
388  free(alias);
389  continue;
390  }
391 
392 
393  status = switch_api_execute(cmd, arg, NULL, istream);
394  }
395 
396  end:
397 
398  switch_safe_free(dup);
399 
400  return status;
401 }
402 
403 SWITCH_DECLARE(void) switch_console_printf(switch_text_channel_t channel, const char *file, const char *func, int line, const char *fmt, ...)
404 {
405  char *data = NULL;
406  int ret = 0;
407  va_list ap;
408  FILE *handle = switch_core_data_channel(channel);
409  const char *filep = switch_cut_path(file);
410  char date[80] = "";
411  switch_size_t retsize;
413  switch_event_t *event;
414 
415  va_start(ap, fmt);
416  ret = switch_vasprintf(&data, fmt, ap);
417  va_end(ap);
418 
419  if (ret == -1) {
420  fprintf(stderr, "Memory Error\n");
421  goto done;
422  }
423 
424  if (channel == SWITCH_CHANNEL_ID_LOG_CLEAN) {
425  fprintf(handle, "%s", data);
426  goto done;
427  }
428 
430  switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
431 
432  if (channel == SWITCH_CHANNEL_ID_LOG) {
433  fprintf(handle, "[%d] %s %s:%d %s() %s", (int) getpid(), date, filep, line, func, data);
434  goto done;
435  }
436 
437  if (channel == SWITCH_CHANNEL_ID_EVENT &&
439 
440  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Data", data);
441  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-File", filep);
442  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Function", func);
443  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Log-Line", "%d", line);
444  switch_event_fire(&event);
445  }
446 
447  done:
448  if (data) {
449  free(data);
450  }
451  fflush(handle);
452 }
453 
454 static int32_t running = 1;
455 
456 struct helper {
457  int len;
458  int hits;
459  int words;
460  char last[512];
461  char partial[512];
462  FILE *out;
465  int xml_off;
466 };
467 
468 static int comp_callback(void *pArg, int argc, char **argv, char **columnNames)
469 {
470  struct helper *h = (struct helper *) pArg;
471  char *target = NULL, *str = NULL, *cur = NULL;
472  switch_size_t x, y, i;
473 
474 
475  if (argc > 0)
476  target = argv[0];
477  if (argc > 1)
478  str = argv[1];
479  if (argc > 2)
480  cur = argv[2];
481 
482  if (cur) {
483  while (*cur == ' ')
484  cur++;
485  }
486 
487  if (zstr(cur))
488  cur = NULL;
489  if (zstr(str))
490  str = NULL;
491 
492  if (!target) {
493  return -1;
494  }
495 
496  if (!zstr(target) && *target == ':' && *(target + 1) == ':' && *(target + 2) == '[') {
497  char *p = target + 3, *list = NULL;
498 
499  if (p) {
500  char *s_argv[100] = { 0 };
501  char *r_argv[1] = { 0 }, *r_cols[1] = {0};
502  list = strdup(p);
503 
504  argc = switch_separate_string(list, ':', s_argv, (sizeof(s_argv) / sizeof(s_argv[0])));
505 
506  for (i = 0; (int)i < argc; i++) {
507  if (!cur || !strncmp(s_argv[i], cur, strlen(cur))) {
508  r_argv[0] = s_argv[i];
509  comp_callback(h, 1, r_argv, r_cols);
510  }
511  }
512  switch_safe_free(list);
513  }
514  return 0;
515  }
516 
517  if (!zstr(target) && *target == ':' && *(target + 1) == ':') {
518  char *r_argv[1] = { 0 }, *r_cols[1] = {0};
520  if (switch_console_run_complete_func(target, str, cur, &matches) == SWITCH_STATUS_SUCCESS) {
522  for (m = matches->head; m; m = m->next) {
523  if (!cur || !strncmp(m->val, cur, strlen(cur))) {
524  r_argv[0] = m->val;
525  comp_callback(h, 1, r_argv, r_cols);
526  }
527  }
528  switch_console_free_matches(&matches);
529  }
530  return 0;
531  }
532 
533  if (!zstr(target)) {
534  if (h->out) {
535  fprintf(h->out, "[%20s]\t", target);
536  }
537  if (h->stream) {
538  h->stream->write_function(h->stream, "[%20s]\t", target);
539  }
540  if (h->xml) {
541  switch_xml_set_txt_d(switch_xml_add_child_d(h->xml, "match", h->xml_off++), target);
542  }
543 
544  switch_copy_string(h->last, target, sizeof(h->last));
545  h->hits++;
546  }
547 
548  x = strlen(h->last);
549  y = strlen(h->partial);
550 
551  if (h->hits > 1) {
552  for (i = 0; i < x && i < y; i++) {
553  if (h->last[i] != h->partial[i]) {
554  h->partial[i] = '\0';
555  break;
556  }
557  }
558  } else if (h->hits == 1) {
559  switch_copy_string(h->partial, target, sizeof(h->last));
560  }
561 
562  if (!zstr(target)) {
563 #ifdef _MSC_VER
564  if ((h->hits % 3) == 0) {
565 #else
566  if ((h->hits % 4) == 0) {
567 #endif
568  if (h->out) {
569  fprintf(h->out, "\n");
570  }
571  if (h->stream) {
572  h->stream->write_function(h->stream, "\n");
573  }
574  }
575  }
576 
577  return 0;
578 }
579 
580 
581 
582 struct match_helper {
584 };
585 
586 static int modulename_callback(void *pArg, const char *module_name)
587 {
588  struct match_helper *h = (struct match_helper *) pArg;
589 
590  switch_console_push_match(&h->my_matches, module_name);
591  return 0;
592 }
593 
595 {
596  struct match_helper h = { 0 };
597 
599  return SWITCH_STATUS_GENERR;
600  }
601 
602  if (h.my_matches) {
603  *matches = h.my_matches;
604  return SWITCH_STATUS_SUCCESS;
605  }
606 
607  return SWITCH_STATUS_FALSE;
608 }
609 
611 {
612  struct match_helper h = { 0 };
613 
615  return SWITCH_STATUS_GENERR;
616  }
617 
618  if (h.my_matches) {
619  *matches = h.my_matches;
620  return SWITCH_STATUS_SUCCESS;
621  }
622 
623  return SWITCH_STATUS_FALSE;
624 }
625 
626 #ifdef HAVE_GETIFADDRS
627 #include <ifaddrs.h>
628 #include <net/if.h>
630 {
631  struct match_helper h = { 0 };
632  struct ifaddrs *addrs, *addr;
633 
634  getifaddrs(&addrs);
635  for(addr = addrs; addr; addr = addr->ifa_next) {
636  if (addr->ifa_flags & IFF_UP) {
637  switch_console_push_match_unique(&h.my_matches, addr->ifa_name);
638  }
639  }
640  freeifaddrs(addrs);
641 
642  if (h.my_matches) {
643  *matches = h.my_matches;
644  return SWITCH_STATUS_SUCCESS;
645  }
646 
647  return SWITCH_STATUS_FALSE;
648 }
649 #else
651 {
652  return SWITCH_STATUS_FALSE;
653 }
654 #endif
655 
656 static int uuid_callback(void *pArg, int argc, char **argv, char **columnNames)
657 {
658  struct match_helper *h = (struct match_helper *) pArg;
659 
661  return 0;
662 
663 }
664 
666 {
667  char *sql;
668  struct match_helper h = { 0 };
669  switch_cache_db_handle_t *db = NULL;
671  char *errmsg;
672 
673 
676  return SWITCH_STATUS_GENERR;
677  }
678 
679  if (!zstr(cursor)) {
680  sql = switch_mprintf("select distinct uuid from channels where uuid like '%q%%' and hostname='%q' order by uuid",
681  cursor, switch_core_get_switchname());
682  } else {
683  sql = switch_mprintf("select distinct uuid from channels where hostname='%q' order by uuid", switch_core_get_switchname());
684  }
685 
687  free(sql);
688 
690 
691  if (h.my_matches) {
692  *matches = h.my_matches;
693  status = SWITCH_STATUS_SUCCESS;
694  }
695 
696 
697  return status;
698 }
699 
700 
701 SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const char *cursor, FILE * console_out,
703 {
704  switch_cache_db_handle_t *db = NULL;
705  char *sql = NULL;
706  char *dup = strdup(line);
707  char *buf = dup;
708  char *p, *lp = NULL;
709  char *errmsg = NULL;
710  struct helper h = { 0 };
711  unsigned char ret = CC_REDISPLAY;
712  int pos = 0;
713  int sc = 0;
714 
715 #ifndef HAVE_LIBEDIT
716 #ifndef _MSC_VER
717  if (!stream) {
718  return CC_ERROR;
719  }
720 #endif
721 #endif
722 
725  switch_safe_free(dup);
726  return CC_ERROR;
727  }
728 
729  if (!zstr(cursor) && !zstr(line)) {
730  pos = (int)(cursor - line);
731  }
732 
733  h.out = console_out;
734  h.stream = stream;
735  h.xml = xml;
736 
737  if (pos > 0) {
738  *(buf + pos) = '\0';
739  }
740 
741  if ((p = strchr(buf, '\r')) || (p = strchr(buf, '\n'))) {
742  *p = '\0';
743  }
744 
745  while (*buf == ' ') {
746  sc++;
747  buf++;
748  }
749 
750  if (!*buf) {
751 #ifdef HAVE_LIBEDIT
752  if (h.out && sc) {
753  el_deletestr(el, sc);
754  }
755 #endif
756  }
757 
758  sc = 0;
759  p = end_of_p(buf);
760  while (p >= buf && *p == ' ') {
761  sc++;
762  p--;
763  }
764 
765  if (sc > 1) {
766 #ifdef HAVE_LIBEDIT
767  if (h.out) {
768  el_deletestr(el, sc - 1);
769  }
770 #endif
771  *(p + 2) = '\0';
772  }
773 
774  for (p = buf; p && *p; p++) {
775  if (*p == ' ') {
776  lp = p;
777  h.words++;
778  while (*p == ' ')
779  p++;
780  if (!*p)
781  break;
782  }
783  }
784 
785  if (lp) {
786  buf = lp + 1;
787  }
788 
789  h.len = (int)strlen(buf);
790 
791  if (h.out) {
792  fprintf(h.out, "\n\n");
793  }
794 
795  if (h.stream) {
796  h.stream->write_function(h.stream, "\n\n");
797  }
798 
799 
800 
801  if (h.words == 0) {
802  sql = switch_mprintf("select distinct name from interfaces where type='api' and name like '%q%%' and hostname='%q' order by name",
803  buf, switch_core_get_hostname());
804  }
805 
806  if (sql) {
808 
809  if (errmsg) {
810  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error [%s][%s]\n", sql, errmsg);
811  free(errmsg);
812  ret = CC_ERROR;
813  goto end;
814  }
815  free(sql);
816  sql = NULL;
817  }
818 
819  if (h.hits != -1) {
820  char *dupdup = strdup(dup);
821  int x, argc = 0;
822  char *argv[10] = { 0 };
823  switch_stream_handle_t stream = { 0 };
824  SWITCH_STANDARD_STREAM(stream);
825  switch_assert(dupdup);
826 
827  argc = switch_separate_string(dupdup, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
828 
829  if (h.words == 0) {
830  stream.write_function(&stream, "select distinct a1 from complete where " "a1 not in (select name from interfaces where hostname='%q') %s ",
831  switch_core_get_hostname(), argc ? "and" : "");
832  } else {
834  stream.write_function(&stream, "select distinct a%d,'%q','%q' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp));
835  } else {
836  stream.write_function(&stream, "select distinct a%d,'%q','%w' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp));
837  }
838  }
839 
840  for (x = 0; x < argc; x++) {
841  if (h.words + 1 > argc) {
843  stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d = '%q')%q",
844  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
845  } else {
846  stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d = '%w')%w",
847  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
848  }
849  } else {
851  stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d like '%q%%')%q",
852  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
853  } else {
854  stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d like '%w%%')%w",
855  x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and ");
856  }
857  }
858  }
859 
860  stream.write_function(&stream, " and hostname='%s' order by a%d", switch_core_get_hostname(), h.words + 1);
861 
862  switch_cache_db_execute_sql_callback(db, stream.data, comp_callback, &h, &errmsg);
863 
864  if (errmsg) {
865  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error [%s][%s]\n", (char *) stream.data, errmsg);
866  free(errmsg);
867  ret = CC_ERROR;
868  }
869 
870  switch_safe_free(dupdup);
871  switch_safe_free(stream.data);
872 
873  if (ret == CC_ERROR) {
874  goto end;
875  }
876  }
877 
878  if (h.out) {
879  fprintf(h.out, "\n\n");
880  }
881 
882  if (h.stream) {
883  h.stream->write_function(h.stream, "\n\n");
884  if (h.hits == 1 && !zstr(h.last)) {
885  h.stream->write_function(h.stream, "write=%d:%s ", h.len, h.last);
886  } else if (h.hits > 1 && !zstr(h.partial)) {
887  h.stream->write_function(h.stream, "write=%d:%s", h.len, h.partial);
888  }
889  }
890 
891  if (h.xml) {
892  switch_xml_t x_write = switch_xml_add_child_d(h.xml, "write", h.xml_off++);
893  char buf[32];
894 
895  snprintf(buf, sizeof(buf), "%d", h.len);
896  switch_xml_set_attr_d_buf(x_write, "length", buf);
897 
898  if (h.hits == 1 && !zstr(h.last)) {
899  switch_xml_set_txt_d(x_write, h.last);
900  } else if (h.hits > 1 && !zstr(h.partial)) {
901  switch_xml_set_txt_d(x_write, h.partial);
902  }
903  }
904 #ifdef HAVE_LIBEDIT
905  if (h.out) {
906  if (h.hits == 1 && !zstr(h.last)) {
907  el_deletestr(el, h.len);
908  el_insertstr(el, h.last);
909  el_insertstr(el, " ");
910  } else if (h.hits > 1 && !zstr(h.partial)) {
911  el_deletestr(el, h.len);
912  el_insertstr(el, h.partial);
913  }
914  }
915 #else
916 #ifdef _MSC_VER
917  if (h.out) {
918  if (h.hits == 1 && !zstr(h.last)) {
919  console_bufferInput(0, h.len, (char *) line, DELETE_REFRESH_OP);
920  console_bufferInput(h.last, (int) strlen(h.last), (char *) line, 0);
921  console_bufferInput(" ", 1, (char *) line, 0);
922  } else if (h.hits > 1 && !zstr(h.partial)) {
923  console_bufferInput(0, h.len, (char *) line, DELETE_REFRESH_OP);
924  console_bufferInput(h.partial, (int) strlen(h.partial), (char *) line, 0);
925  } else {
926  console_bufferInput(0, 0, (char *) line, DELETE_REFRESH_OP);
927  }
928  }
929 #endif
930 #endif
931 
932  end:
933 
934  if (h.out) {
935  fflush(h.out);
936  }
937 
938  switch_safe_free(sql);
939  switch_safe_free(dup);
940 
942 
943  return (ret);
944 }
945 
946 
947 #if defined(HAVE_LIBEDIT) || defined(_MSC_VER)
948 /*
949  * If a fnkey is configured then process the command
950  */
951 static unsigned char console_fnkey_pressed(int i)
952 {
953  char *c, *cmd;
954 
955  switch_assert((i > 0) && (i <= 12));
956 
957  c = console_fnkeys[i - 1];
958 
959  /* This new line is necessary to avoid output to begin after the ">" of the CLI's prompt */
961 
962  if (c == NULL) {
963  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "FUNCTION KEY F%d IS NOT BOUND, please edit switch.conf XML file\n", i);
964  return CC_REDISPLAY;
965  }
966 
967  cmd = strdup(c);
969  free(cmd);
970 
971  return CC_REDISPLAY;
972 }
973 #endif
974 
976 {
977 #ifdef HAVE_LIBEDIT
978  history(myhistory, &ev, H_SAVE, hfile);
979 #else
981 #endif
982 }
983 
984 #ifdef HAVE_LIBEDIT
985 static char prompt_str[512] = "";
986 
987 static unsigned char console_f1key(EditLine * el, int ch)
988 {
989  return console_fnkey_pressed(1);
990 }
991 static unsigned char console_f2key(EditLine * el, int ch)
992 {
993  return console_fnkey_pressed(2);
994 }
995 static unsigned char console_f3key(EditLine * el, int ch)
996 {
997  return console_fnkey_pressed(3);
998 }
999 static unsigned char console_f4key(EditLine * el, int ch)
1000 {
1001  return console_fnkey_pressed(4);
1002 }
1003 static unsigned char console_f5key(EditLine * el, int ch)
1004 {
1005  return console_fnkey_pressed(5);
1006 }
1007 static unsigned char console_f6key(EditLine * el, int ch)
1008 {
1009  return console_fnkey_pressed(6);
1010 }
1011 static unsigned char console_f7key(EditLine * el, int ch)
1012 {
1013  return console_fnkey_pressed(7);
1014 }
1015 static unsigned char console_f8key(EditLine * el, int ch)
1016 {
1017  return console_fnkey_pressed(8);
1018 }
1019 static unsigned char console_f9key(EditLine * el, int ch)
1020 {
1021  return console_fnkey_pressed(9);
1022 }
1023 static unsigned char console_f10key(EditLine * el, int ch)
1024 {
1025  return console_fnkey_pressed(10);
1026 }
1027 static unsigned char console_f11key(EditLine * el, int ch)
1028 {
1029  return console_fnkey_pressed(11);
1030 }
1031 static unsigned char console_f12key(EditLine * el, int ch)
1032 {
1033  return console_fnkey_pressed(12);
1034 }
1035 
1036 
1037 char *prompt(EditLine * e)
1038 {
1039  if (*prompt_str == '\0') {
1040  switch_snprintf(prompt_str, sizeof(prompt_str), "freeswitch@%s> ", switch_core_get_switchname());
1041  }
1042 
1043  return prompt_str;
1044 }
1045 
1046 static void *SWITCH_THREAD_FUNC console_thread(switch_thread_t *thread, void *obj)
1047 {
1048  int count;
1049  const char *line;
1051 
1052  while (running) {
1053  int32_t arg = 0;
1054 
1055  if (getppid() == 1) {
1056  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "We've become an orphan, no more console for us.\n");
1057  break;
1058  }
1059 
1061  if (!arg) {
1062  break;
1063  }
1064 
1065  line = el_gets(el, &count);
1066 
1067  if (count > 1) {
1068  if (!zstr(line)) {
1069  char *cmd = strdup(line);
1070  char *p;
1071  const LineInfo *lf = el_line(el);
1072  char *foo = (char *) lf->buffer;
1073  if ((p = strrchr(cmd, '\r')) || (p = strrchr(cmd, '\n'))) {
1074  *p = '\0';
1075  }
1076  assert(cmd != NULL);
1077  history(myhistory, &ev, H_ENTER, line);
1079  el_deletestr(el, strlen(foo) + 1);
1080  memset(foo, 0, strlen(foo));
1081  free(cmd);
1082  }
1083  }
1084  switch_cond_next();
1085  }
1086 
1088  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Editline thread exiting\n");
1089  return NULL;
1090 }
1091 
1092 static unsigned char complete(EditLine * el, int ch)
1093 {
1094  const LineInfo *lf = el_line(el);
1095 
1096  return switch_console_complete(lf->buffer, lf->cursor, switch_core_get_console(), NULL, NULL);
1097 }
1098 
1099 
1101 {
1103  switch_threadattr_t *thd_attr = NULL;
1105 
1108  return;
1109  }
1110 
1112  el_set(el, EL_PROMPT, &prompt);
1113  el_set(el, EL_EDITOR, "emacs");
1114  /* AGX: Bind Keyboard function keys. This has been tested with:
1115  * - linux console keyabord
1116  * - putty.exe connected via ssh to linux
1117  */
1118  /* Load/Init the config first */
1120  /* Bind the functions to the key */
1121  el_set(el, EL_ADDFN, "f1-key", "F1 KEY PRESS", console_f1key);
1122  el_set(el, EL_ADDFN, "f2-key", "F2 KEY PRESS", console_f2key);
1123  el_set(el, EL_ADDFN, "f3-key", "F3 KEY PRESS", console_f3key);
1124  el_set(el, EL_ADDFN, "f4-key", "F4 KEY PRESS", console_f4key);
1125  el_set(el, EL_ADDFN, "f5-key", "F5 KEY PRESS", console_f5key);
1126  el_set(el, EL_ADDFN, "f6-key", "F6 KEY PRESS", console_f6key);
1127  el_set(el, EL_ADDFN, "f7-key", "F7 KEY PRESS", console_f7key);
1128  el_set(el, EL_ADDFN, "f8-key", "F8 KEY PRESS", console_f8key);
1129  el_set(el, EL_ADDFN, "f9-key", "F9 KEY PRESS", console_f9key);
1130  el_set(el, EL_ADDFN, "f10-key", "F10 KEY PRESS", console_f10key);
1131  el_set(el, EL_ADDFN, "f11-key", "F11 KEY PRESS", console_f11key);
1132  el_set(el, EL_ADDFN, "f12-key", "F12 KEY PRESS", console_f12key);
1133 
1134  el_set(el, EL_BIND, "\033OP", "f1-key", NULL);
1135  el_set(el, EL_BIND, "\033OQ", "f2-key", NULL);
1136  el_set(el, EL_BIND, "\033OR", "f3-key", NULL);
1137  el_set(el, EL_BIND, "\033OS", "f4-key", NULL);
1138 
1139 
1140  el_set(el, EL_BIND, "\033[11~", "f1-key", NULL);
1141  el_set(el, EL_BIND, "\033[12~", "f2-key", NULL);
1142  el_set(el, EL_BIND, "\033[13~", "f3-key", NULL);
1143  el_set(el, EL_BIND, "\033[14~", "f4-key", NULL);
1144  el_set(el, EL_BIND, "\033[15~", "f5-key", NULL);
1145  el_set(el, EL_BIND, "\033[17~", "f6-key", NULL);
1146  el_set(el, EL_BIND, "\033[18~", "f7-key", NULL);
1147  el_set(el, EL_BIND, "\033[19~", "f8-key", NULL);
1148  el_set(el, EL_BIND, "\033[20~", "f9-key", NULL);
1149  el_set(el, EL_BIND, "\033[21~", "f10-key", NULL);
1150  el_set(el, EL_BIND, "\033[23~", "f11-key", NULL);
1151  el_set(el, EL_BIND, "\033[24~", "f12-key", NULL);
1152 
1153 
1154  el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
1155  el_set(el, EL_BIND, "^I", "ed-complete", NULL);
1156 
1157  /* "Delete" key. */
1158  el_set(el, EL_BIND, "\033[3~", "ed-delete-next-char", NULL);
1159 
1160  myhistory = history_init();
1161  if (myhistory == 0) {
1162  fprintf(stderr, "history could not be initialized\n");
1163  return;
1164  }
1165 
1166  hfile = switch_mprintf("%s%sfreeswitch.history", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
1167  assert(hfile != NULL);
1168 
1169  history(myhistory, &ev, H_SETSIZE, 800);
1170  el_set(el, EL_HIST, history, myhistory);
1171  history(myhistory, &ev, H_LOAD, hfile);
1172 
1173  el_source(el, NULL);
1174 
1175  switch_threadattr_create(&thd_attr, pool);
1176  switch_threadattr_detach_set(thd_attr, 1);
1178  switch_thread_create(&thread, thd_attr, console_thread, pool, pool);
1179 
1180  while (running) {
1181  int32_t arg = 0;
1183  if (!arg) {
1184  break;
1185  }
1186  switch_yield(1000000);
1187  }
1188 
1189  history(myhistory, &ev, H_SAVE, hfile);
1190  free(hfile);
1191 
1192  /* Clean up our memory */
1193  history_end(myhistory);
1194  el_end(el);
1195 }
1196 
1197 #else
1198 
1199 #ifdef _MSC_VER
1200 char history[HISTLEN][CMD_BUFLEN + 1];
1201 int iHistory = 0;
1202 int iHistorySel = 0;
1203 
1204 static int console_history(char *cmd, int direction)
1205 {
1206  int i;
1207  static int first;
1208 
1209  if (direction == 0) {
1210  first = 1;
1211  if (iHistory < HISTLEN) {
1212  if (iHistory && strcmp(history[iHistory - 1], cmd)) {
1213  iHistorySel = iHistory;
1214  strcpy(history[iHistory++], cmd);
1215  } else if (iHistory == 0) {
1216  iHistorySel = iHistory;
1217  strcpy(history[iHistory++], cmd);
1218  }
1219  } else {
1220  iHistory = HISTLEN - 1;
1221  for (i = 0; i < HISTLEN - 1; i++) {
1222  strcpy(history[i], history[i + 1]);
1223  }
1224  iHistorySel = iHistory;
1225  strcpy(history[iHistory++], cmd);
1226  }
1227  } else {
1228  if (!first) {
1229  iHistorySel += direction;
1230  }
1231  first = 0;
1232  if (iHistorySel < 0) {
1233  iHistorySel = 0;
1234  }
1235  if (iHistory && iHistorySel >= iHistory) {
1236  iHistorySel = iHistory - 1;
1237  }
1238  strcpy(cmd, history[iHistorySel]);
1239  }
1240  return (SWITCH_STATUS_SUCCESS);
1241 }
1242 
1243 static int console_bufferInput(char *addchars, int len, char *cmd, int key)
1244 {
1245  static int iCmdBuffer = 0;
1246  static int iCmdCursor = 0;
1247  static int ignoreNext = 0;
1248  static int insertMode = 1;
1249  static COORD orgPosition;
1250  static char prompt[80];
1251  int iBuf;
1252  int i;
1253 
1254  HANDLE hOut;
1255  CONSOLE_SCREEN_BUFFER_INFO info;
1256  COORD position;
1257  hOut = GetStdHandle(STD_OUTPUT_HANDLE);
1258  GetConsoleScreenBufferInfo(hOut, &info);
1259  position = info.dwCursorPosition;
1260  if (iCmdCursor == 0) {
1261  orgPosition = position;
1262  }
1263 
1264  if (key == PROMPT_OP) {
1265  if (strlen(cmd) < sizeof(prompt)) {
1266  strcpy(prompt, cmd);
1267  }
1268  return 0;
1269  }
1270 
1271  if (key == KEY_TAB) {
1272  switch_console_complete(cmd, cmd + iCmdBuffer, switch_core_get_console(), NULL, NULL);
1273  return 0;
1274  }
1275  if (key == KEY_UP || key == KEY_DOWN || key == CLEAR_OP) {
1276  SetConsoleCursorPosition(hOut, orgPosition);
1277  for (i = 0; i < (int) strlen(cmd); i++) {
1278  printf(" ");
1279  }
1280  SetConsoleCursorPosition(hOut, orgPosition);
1281  iCmdBuffer = 0;
1282  iCmdCursor = 0;
1283  memset(cmd, 0, CMD_BUFLEN);
1284  }
1285  if (key == DELETE_REFRESH_OP) {
1286  int l = len < (int) strlen(cmd) ? len : (int) strlen(cmd);
1287  for (i = 0; i < l; i++) {
1288  cmd[--iCmdBuffer] = 0;
1289  }
1290  iCmdCursor = (int) strlen(cmd);
1291  printf("%s", prompt);
1292  GetConsoleScreenBufferInfo(hOut, &info);
1293  orgPosition = info.dwCursorPosition;
1294  printf("%s", cmd);
1295  return 0;
1296  }
1297 
1298  if (key == KEY_LEFT) {
1299  if (iCmdCursor) {
1300  if (position.X == 0) {
1301  position.Y -= 1;
1302  position.X = info.dwSize.X - 1;
1303  } else {
1304  position.X -= 1;
1305  }
1306 
1307  SetConsoleCursorPosition(hOut, position);
1308  iCmdCursor--;
1309  }
1310  }
1311  if (key == KEY_RIGHT) {
1312  if (iCmdCursor < (int) strlen(cmd)) {
1313  if (position.X == info.dwSize.X - 1) {
1314  position.Y += 1;
1315  position.X = 0;
1316  } else {
1317  position.X += 1;
1318  }
1319 
1320  SetConsoleCursorPosition(hOut, position);
1321  iCmdCursor++;
1322  }
1323  }
1324  if (key == KEY_INSERT) {
1325  insertMode = !insertMode;
1326  }
1327  if (key == KEY_DELETE) {
1328  if (iCmdCursor < iCmdBuffer) {
1329  int pos;
1330  for (pos = iCmdCursor; pos < iCmdBuffer; pos++) {
1331  cmd[pos] = cmd[pos + 1];
1332  }
1333  cmd[pos] = 0;
1334  iCmdBuffer--;
1335 
1336  for (pos = iCmdCursor; pos < iCmdBuffer; pos++) {
1337  printf("%c", cmd[pos]);
1338  }
1339  printf(" ");
1340  SetConsoleCursorPosition(hOut, position);
1341  }
1342  }
1343  for (iBuf = 0; iBuf < len; iBuf++) {
1344  switch (addchars[iBuf]) {
1345  case '\r':
1346  case '\n':
1347  if (ignoreNext) {
1348  ignoreNext = 0;
1349  } else {
1350  int ret = iCmdBuffer;
1351  if (iCmdBuffer == 0) {
1352  strcpy(cmd, "Empty");
1353  ret = (int) strlen(cmd);
1354  } else {
1355  console_history(cmd, 0);
1356  cmd[iCmdBuffer] = 0;
1357  }
1358  iCmdBuffer = 0;
1359  iCmdCursor = 0;
1360  printf("\n");
1361  return (ret);
1362  }
1363  break;
1364  case '\b':
1365  if (iCmdCursor) {
1366  if (position.X == 0) {
1367  position.Y -= 1;
1368  position.X = info.dwSize.X - 1;
1369  SetConsoleCursorPosition(hOut, position);
1370  } else {
1371  position.X -= 1;
1372  SetConsoleCursorPosition(hOut, position);
1373  }
1374  printf(" ");
1375  if (iCmdCursor < iCmdBuffer) {
1376  int pos;
1377  iCmdCursor--;
1378  for (pos = iCmdCursor; pos < iCmdBuffer; pos++) {
1379  cmd[pos] = cmd[pos + 1];
1380  }
1381  cmd[pos] = 0;
1382  iCmdBuffer--;
1383 
1384  SetConsoleCursorPosition(hOut, position);
1385  for (pos = iCmdCursor; pos < iCmdBuffer; pos++) {
1386  printf("%c", cmd[pos]);
1387  }
1388  printf(" ");
1389  SetConsoleCursorPosition(hOut, position);
1390  } else {
1391  SetConsoleCursorPosition(hOut, position);
1392  iCmdBuffer--;
1393  iCmdCursor--;
1394  cmd[iCmdBuffer] = 0;
1395  }
1396  }
1397  break;
1398  default:
1399  if (!ignoreNext) {
1400  if (iCmdCursor < iCmdBuffer) {
1401  int pos;
1402 
1403  if (position.X == info.dwSize.X - 1) {
1404  position.Y += 1;
1405  position.X = 0;
1406  } else {
1407  position.X += 1;
1408  }
1409 
1410  if (insertMode) {
1411  for (pos = iCmdBuffer - 1; pos >= iCmdCursor; pos--) {
1412  cmd[pos + 1] = cmd[pos];
1413  }
1414  }
1415  iCmdBuffer++;
1416  cmd[iCmdCursor++] = addchars[iBuf];
1417  printf("%c", addchars[iBuf]);
1418  for (pos = iCmdCursor; pos < iCmdBuffer; pos++) {
1419  GetConsoleScreenBufferInfo(hOut, &info);
1420  if (info.dwCursorPosition.X == info.dwSize.X - 1 && info.dwCursorPosition.Y == info.dwSize.Y - 1) {
1421  orgPosition.Y -= 1;
1422  position.Y -= 1;
1423  }
1424  printf("%c", cmd[pos]);
1425  }
1426  SetConsoleCursorPosition(hOut, position);
1427  } else {
1428  if (position.X == info.dwSize.X - 1 && position.Y == info.dwSize.Y - 1) {
1429  orgPosition.Y -= 1;
1430  }
1431  cmd[iCmdBuffer++] = addchars[iBuf];
1432  iCmdCursor++;
1433  printf("%c", addchars[iBuf]);
1434  }
1435  }
1436  }
1437  if (iCmdBuffer == CMD_BUFLEN) {
1438  printf("Read Console... BUFFER OVERRUN\n");
1439  iCmdBuffer = 0;
1440  ignoreNext = 1;
1441  }
1442  }
1443  return (SWITCH_STATUS_SUCCESS);
1444 }
1445 
1446 
1447 static BOOL console_readConsole(HANDLE conIn, char *buf, int len, int *pRed, int *key)
1448 {
1449  DWORD recordIndex, bufferIndex, toRead = 0, red;
1450  PINPUT_RECORD pInput;
1451 
1452  GetNumberOfConsoleInputEvents(conIn, &toRead);
1453  if (len < (int) toRead) {
1454  toRead = len;
1455  }
1456  if (toRead == 0) {
1457  return (FALSE);
1458  }
1459 
1460  if ((pInput = (PINPUT_RECORD) malloc(toRead * sizeof(INPUT_RECORD))) == NULL) {
1461  return (FALSE);
1462  }
1463  *key = 0;
1464  ReadConsoleInput(conIn, pInput, toRead, &red);
1465 
1466  for (recordIndex = bufferIndex = 0; recordIndex < red; recordIndex++) {
1467  KEY_EVENT_RECORD keyEvent = pInput[recordIndex].Event.KeyEvent;
1468  if (pInput[recordIndex].EventType == KEY_EVENT && keyEvent.bKeyDown) {
1469  if (keyEvent.wVirtualKeyCode == 38 && keyEvent.wVirtualScanCode == 72) {
1470  buf[0] = 0;
1471  console_history(buf, -1);
1472  *key = KEY_UP;
1473  bufferIndex += (DWORD) strlen(buf);
1474  }
1475  if (keyEvent.wVirtualKeyCode == 40 && keyEvent.wVirtualScanCode == 80) {
1476  buf[0] = 0;
1477  console_history(buf, 1);
1478  *key = KEY_DOWN;
1479  bufferIndex += (DWORD) strlen(buf);
1480  }
1481  if (keyEvent.wVirtualKeyCode == 112 && keyEvent.wVirtualScanCode == 59) {
1482  console_fnkey_pressed(1);
1483  }
1484  if (keyEvent.wVirtualKeyCode == 113 && keyEvent.wVirtualScanCode == 60) {
1485  console_fnkey_pressed(2);
1486  }
1487  if (keyEvent.wVirtualKeyCode == 114 && keyEvent.wVirtualScanCode == 61) {
1488  console_fnkey_pressed(3);
1489  }
1490  if (keyEvent.wVirtualKeyCode == 115 && keyEvent.wVirtualScanCode == 62) {
1491  console_fnkey_pressed(4);
1492  }
1493  if (keyEvent.wVirtualKeyCode == 116 && keyEvent.wVirtualScanCode == 63) {
1494  console_fnkey_pressed(5);
1495  }
1496  if (keyEvent.wVirtualKeyCode == 117 && keyEvent.wVirtualScanCode == 64) {
1497  console_fnkey_pressed(6);
1498  }
1499  if (keyEvent.wVirtualKeyCode == 118 && keyEvent.wVirtualScanCode == 65) {
1500  console_fnkey_pressed(7);
1501  }
1502  if (keyEvent.wVirtualKeyCode == 119 && keyEvent.wVirtualScanCode == 66) {
1503  console_fnkey_pressed(8);
1504  }
1505  if (keyEvent.wVirtualKeyCode == 120 && keyEvent.wVirtualScanCode == 67) {
1506  console_fnkey_pressed(9);
1507  }
1508  if (keyEvent.wVirtualKeyCode == 121 && keyEvent.wVirtualScanCode == 68) {
1509  console_fnkey_pressed(10);
1510  }
1511  if (keyEvent.wVirtualKeyCode == 122 && keyEvent.wVirtualScanCode == 87) {
1512  console_fnkey_pressed(11);
1513  }
1514  if (keyEvent.wVirtualKeyCode == 123 && keyEvent.wVirtualScanCode == 88) {
1515  console_fnkey_pressed(12);
1516  }
1517  if (keyEvent.uChar.AsciiChar == 9) {
1518  *key = KEY_TAB;
1519  break;
1520  }
1521  if (keyEvent.uChar.AsciiChar == 27) {
1522  *key = CLEAR_OP;
1523  break;
1524  }
1525  if (keyEvent.wVirtualKeyCode == 37 && keyEvent.wVirtualScanCode == 75) {
1526  *key = KEY_LEFT;
1527  }
1528  if (keyEvent.wVirtualKeyCode == 39 && keyEvent.wVirtualScanCode == 77) {
1529  *key = KEY_RIGHT;
1530  }
1531  if (keyEvent.wVirtualKeyCode == 45 && keyEvent.wVirtualScanCode == 82) {
1532  *key = KEY_INSERT;
1533  }
1534  if (keyEvent.wVirtualKeyCode == 46 && keyEvent.wVirtualScanCode == 83) {
1535  *key = KEY_DELETE;
1536  }
1537  while (keyEvent.wRepeatCount && keyEvent.uChar.AsciiChar) {
1538  buf[bufferIndex] = keyEvent.uChar.AsciiChar;
1539  if (buf[bufferIndex] == '\r') {
1540  buf[bufferIndex] = '\n';
1541  }
1542  bufferIndex++;
1543  keyEvent.wRepeatCount--;
1544  }
1545  }
1546  }
1547 
1548  free(pInput);
1549  *pRed = bufferIndex;
1550  return (TRUE);
1551 }
1552 #endif
1553 
1554 
1556 {
1557  char cmd[CMD_BUFLEN + 1] = "";
1558  int32_t activity = 1;
1559 #ifndef _MSC_VER
1560  int x = 0;
1561 #else
1562  char keys[CMD_BUFLEN];
1563 #endif
1564 
1565  /* Load/Init the config first */
1567 
1568 #ifdef _MSC_VER
1569  sprintf(cmd, "\nfreeswitch@%s> ", switch_core_get_switchname());
1570  console_bufferInput(0, 0, cmd, PROMPT_OP);
1571  memset(cmd, 0, sizeof(cmd));
1572 #endif
1573 
1574  while (running) {
1575  int32_t arg;
1576 #ifdef _MSC_VER
1577  int read, key;
1578  HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
1579 #else
1580  fd_set rfds, efds;
1581  struct timeval tv = { 0, 20000 };
1582 #endif
1583 
1585  if (!arg) {
1586  break;
1587  }
1588 
1589  if (activity) {
1591  }
1592 #ifdef _MSC_VER
1593  activity = 0;
1594  if (console_readConsole(stdinHandle, keys, (int) sizeof(keys), &read, &key)) {
1595  if (console_bufferInput(keys, read, cmd, key)) {
1596  if (!strcmp(cmd, "Empty")) {
1597  cmd[0] = 0;
1598  }
1599  activity = 1;
1600  if (cmd[0]) {
1602  }
1603  memset(cmd, 0, sizeof(cmd));
1604  }
1605  }
1606  Sleep(20);
1607 #else
1608  FD_ZERO(&rfds);
1609  FD_ZERO(&efds);
1610  FD_SET(fileno(stdin), &rfds);
1611  FD_SET(fileno(stdin), &efds);
1612  if ((activity = select(fileno(stdin) + 1, &rfds, NULL, &efds, &tv)) < 0) {
1613  break;
1614  }
1615 
1616  if (FD_ISSET(fileno(stdin), &efds)) {
1617  continue;
1618  }
1619 
1620  if (!FD_ISSET(fileno(stdin), &rfds)) {
1621  activity = 0;
1622  }
1623 
1624  if (activity == 0) {
1625  fflush(stdout);
1626  continue;
1627  }
1628 
1629  memset(&cmd, 0, sizeof(cmd));
1630  for (x = 0; x < (sizeof(cmd) - 1); x++) {
1631  int c = getchar();
1632  if (c < 0) {
1633  int y = read(fileno(stdin), cmd, sizeof(cmd) - 1);
1634  cmd[y - 1] = '\0';
1635  break;
1636  }
1637 
1638  cmd[x] = (char) c;
1639 
1640  if (cmd[x] == '\n') {
1641  cmd[x] = '\0';
1642  break;
1643  }
1644  }
1645 
1646  if (cmd[0]) {
1648  }
1649 #endif
1650  }
1651 }
1652 
1653 
1654 
1655 #endif
1656 
1657 
1658 static struct {
1661 } globals;
1662 
1664 {
1665  switch_mutex_init(&globals.func_mutex, SWITCH_MUTEX_NESTED, pool);
1666  switch_core_hash_init(&globals.func_hash);
1671  return SWITCH_STATUS_SUCCESS;
1672 }
1673 
1675 {
1676  return switch_core_hash_destroy(&globals.func_hash);
1677 }
1678 
1680 {
1681  switch_status_t status;
1682 
1683  switch_mutex_lock(globals.func_mutex);
1684  status = switch_core_hash_insert(globals.func_hash, name, (void *) (intptr_t) cb);
1685  switch_mutex_unlock(globals.func_mutex);
1686 
1687  return status;
1688 }
1689 
1691 {
1692  switch_status_t status;
1693 
1694  switch_mutex_lock(globals.func_mutex);
1695  status = switch_core_hash_insert(globals.func_hash, name, NULL);
1696  switch_mutex_unlock(globals.func_mutex);
1697 
1698  return status;
1699 }
1700 
1702 {
1703  switch_console_callback_match_t *my_match = *matches;
1705 
1706  /* Don't play with matches */
1707  *matches = NULL;
1708 
1709  m = my_match->head;
1710  while (m) {
1711  cur = m;
1712  m = m->next;
1713  free(cur->val);
1714  free(cur);
1715  }
1716 
1717  if (my_match->dynamic) {
1718  free(my_match);
1719  }
1720 }
1721 
1723 {
1724  switch_console_callback_match_node_t *p = NULL, *sort[4] = { 0 };
1725  int i, j;
1726 
1727  switch_assert(matches);
1728 
1729  if (matches->count < 2) {
1730  return;
1731  }
1732 
1733  for (i = 1; i < matches->count; i++) {
1734  sort[0] = NULL;
1735  sort[1] = matches->head;
1736  sort[2] = sort[1] ? sort[1]->next : NULL;
1737  sort[3] = sort[2] ? sort[2]->next : NULL;
1738 
1739  for (j = 1; j <= (matches->count - i); j++) {
1740  switch_assert(sort[1] && sort[2]);
1741  if (strcmp(sort[1]->val, sort[2]->val) > 0) {
1742  sort[1]->next = sort[3];
1743  sort[2]->next = sort[1];
1744 
1745  if (sort[0])
1746  sort[0]->next = sort[2];
1747  if (sort[1] == matches->head)
1748  matches->head = sort[2];
1749 
1750 
1751 
1752 
1753  sort[0] = sort[2];
1754  sort[2] = sort[1]->next;
1755  if (sort[3] && sort[3]->next)
1756  sort[3] = sort[3]->next;
1757 
1758  } else {
1759  sort[0] = sort[1];
1760  sort[1] = sort[2];
1761  sort[2] = sort[3];
1762  if (sort[3] && sort[3]->next)
1763  sort[3] = sort[3]->next;
1764  }
1765 
1766  }
1767  }
1768 
1769  p = matches->head;
1770 
1771  for (i = 1; i < matches->count; i++)
1772  p = p->next;
1773 
1774  if (p) {
1775  p->next = NULL;
1776  matches->end = p;
1777  }
1778 }
1779 
1781 {
1782  /* Ignore the entry if it is already in the list */
1783  if (*matches) {
1785 
1786  for(node = (*matches)->head; node; node = node->next) {
1787  if (!strcasecmp(node->val, new_val)) return;
1788  }
1789  }
1790 
1791  switch_console_push_match(matches, new_val);
1792 }
1793 
1795 {
1797 
1798  if (!*matches) {
1799  switch_zmalloc(*matches, sizeof(**matches));
1800  (*matches)->dynamic = 1;
1801  }
1802 
1803  switch_zmalloc(match, sizeof(*match));
1804  match->val = strdup(new_val);
1805 
1806  if ((*matches)->head) {
1807  (*matches)->end->next = match;
1808  } else {
1809  (*matches)->head = match;
1810  }
1811 
1812  (*matches)->count++;
1813 
1814  (*matches)->end = match;
1815 }
1816 
1817 SWITCH_DECLARE(switch_status_t) switch_console_run_complete_func(const char *func, const char *line, const char *last_word,
1819 {
1822 
1823  switch_mutex_lock(globals.func_mutex);
1824  if ((cb = (switch_console_complete_callback_t) (intptr_t) switch_core_hash_find(globals.func_hash, func))) {
1825  if ((status = cb(line, last_word, matches)) == SWITCH_STATUS_SUCCESS) {
1826  switch_console_sort_matches(*matches);
1827  }
1828  }
1829  switch_mutex_unlock(globals.func_mutex);
1830 
1831  return status;
1832 }
1833 
1834 
1836 {
1837  char *mydata = NULL, *argv[11] = { 0 };
1838  int argc, x;
1841 
1842  if (!(cflags & SCF_USE_SQL)) {
1843  return SWITCH_STATUS_FALSE;
1844  }
1845 
1846  if (string && (mydata = strdup(string))) {
1847  if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
1848  switch_stream_handle_t mystream = { 0 };
1849  SWITCH_STANDARD_STREAM(mystream);
1850 
1851  if (!strcasecmp(argv[0], "stickyadd")) {
1852  mystream.write_function(&mystream, "insert into complete (sticky, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, hostname) values (1,");
1853  for (x = 0; x < 10; x++) {
1854  if (argv[x + 1] && !strcasecmp(argv[x + 1], "_any_")) {
1855  mystream.write_function(&mystream, "%s", "'', ");
1856  } else {
1858  mystream.write_function(&mystream, "'%q', ", switch_str_nil(argv[x + 1]));
1859  } else {
1860  mystream.write_function(&mystream, "'%w', ", switch_str_nil(argv[x + 1]));
1861  }
1862  }
1863  }
1864  mystream.write_function(&mystream, " '%s')", switch_core_get_hostname());
1865  switch_core_sql_exec(mystream.data);
1866  status = SWITCH_STATUS_SUCCESS;
1867  } else if (!strcasecmp(argv[0], "add")) {
1868  mystream.write_function(&mystream, "insert into complete (sticky, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, hostname) values (0,");
1869  for (x = 0; x < 10; x++) {
1870  if (argv[x + 1] && !strcasecmp(argv[x + 1], "_any_")) {
1871  mystream.write_function(&mystream, "%s", "'', ");
1872  } else {
1874  mystream.write_function(&mystream, "'%q', ", switch_str_nil(argv[x + 1]));
1875  } else {
1876  mystream.write_function(&mystream, "'%w', ", switch_str_nil(argv[x + 1]));
1877  }
1878  }
1879  }
1880  mystream.write_function(&mystream, " '%s')", switch_core_get_hostname());
1881 
1882  switch_core_sql_exec(mystream.data);
1883  status = SWITCH_STATUS_SUCCESS;
1884  } else if (!strcasecmp(argv[0], "del")) {
1885  char *what = argv[1];
1886  if (zstr(what)) {
1887  switch_safe_free(mystream.data);
1888  switch_safe_free(mydata);
1889  return SWITCH_STATUS_FALSE;
1890  } else if (!strcasecmp(what, "*")) {
1891  mystream.write_function(&mystream, "delete from complete where hostname='%q'", switch_core_get_hostname());
1892  switch_core_sql_exec(mystream.data);
1893  } else {
1894  mystream.write_function(&mystream, "delete from complete where ");
1895  for (x = 0; x < argc - 1; x++) {
1897  mystream.write_function(&mystream, "a%d = '%q'%q", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and ");
1898  } else {
1899  mystream.write_function(&mystream, "a%d = '%w'%w", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and ");
1900  }
1901  }
1902  mystream.write_function(&mystream, " and hostname='%q'", switch_core_get_hostname());
1903  switch_core_sql_exec(mystream.data);
1904  }
1905  status = SWITCH_STATUS_SUCCESS;
1906  }
1907 
1908  switch_safe_free(mystream.data);
1909  }
1910  }
1911 
1912  switch_safe_free(mydata);
1913 
1914  return status;
1915 
1916 }
1917 
1918 
1920 {
1921  char *mydata = NULL, *argv[3] = { 0 };
1922  int argc;
1924 
1925  if (string && (mydata = strdup(string))) {
1926  if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) {
1927  switch_cache_db_handle_t *db = NULL;
1928  char *sql = NULL;
1929 
1930  if (argc > 2 && !strcmp(argv[1], argv[2])) {
1931  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Alias and command cannot be the same, this will cause loop!\n");
1932  return SWITCH_STATUS_FALSE;
1933  }
1934 
1937  free(mydata);
1938  return SWITCH_STATUS_FALSE;
1939  }
1940 
1941  if (!strcasecmp(argv[0], "stickyadd") && argc == 3) {
1942  sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_switchname());
1944  switch_safe_free(sql);
1946  sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (1, '%q','%q','%q')",
1947  argv[1], argv[2], switch_core_get_switchname());
1948  } else {
1949  sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (1, '%w','%w','%w')",
1950  argv[1], argv[2], switch_core_get_switchname());
1951  }
1953  status = SWITCH_STATUS_SUCCESS;
1954  } else if (!strcasecmp(argv[0], "add") && argc == 3) {
1955  sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_switchname());
1957  switch_safe_free(sql);
1959  sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (0, '%q','%q','%q')",
1960  argv[1], argv[2], switch_core_get_switchname());
1961  } else {
1962  sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (0, '%w','%w','%w')",
1963  argv[1], argv[2], switch_core_get_switchname());
1964  }
1966  status = SWITCH_STATUS_SUCCESS;
1967  } else if (!strcasecmp(argv[0], "del") && argc == 2) {
1968  char *what = argv[1];
1969  if (!strcasecmp(what, "*")) {
1970  sql = switch_mprintf("delete from aliases where hostname='%q'", switch_core_get_switchname());
1972  } else {
1973  sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_switchname());
1975  }
1976  status = SWITCH_STATUS_SUCCESS;
1977  }
1978  switch_safe_free(sql);
1980  }
1981  }
1982 
1983  switch_safe_free(mydata);
1984 
1985  return status;
1986 
1987 }
1988 
1989 
1990 
1991 
1992 /* For Emacs:
1993  * Local Variables:
1994  * mode:c
1995  * indent-tabs-mode:t
1996  * tab-width:4
1997  * c-basic-offset:4
1998  * End:
1999  * For VIM:
2000  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2001  */
switch_xml_t switch_xml_set_attr_d_buf(switch_xml_t xml, const char *name, const char *value)
Wrapper for switch_xml_set_attr() that strdup()s name/value. Value cannot be NULL.
Definition: switch_xml.c:3085
switch_xml_t switch_xml_add_child_d(_In_ switch_xml_t xml, _In_z_ const char *name, _In_ switch_size_t off)
wrapper for switch_xml_add_child() that strdup()s name
#define switch_core_permanent_strdup(_todup)
Copy a string using permanent memory allocation.
Definition: switch_core.h:707
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
const char * switch_core_get_switchname(void)
Definition: switch_core.c:361
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
switch_status_t switch_console_set_complete(const char *string)
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
const char * switch_xml_attr_soft(_In_ switch_xml_t xml, _In_z_ const char *attr)
returns the value of the requested tag attribute, or "" if not found
switch_xml_t switch_status_t switch_event_running(void)
Determine if the event system has been initialized.
Definition: switch_event.c:425
#define CC_ERROR
switch_status_t switch_console_shutdown(void)
#define SWITCH_THREAD_FUNC
switch_text_channel_t
A target to write log/debug info to.
#define CC_REDISPLAY
#define SWITCH_CHANNEL_LOG
void switch_console_push_match_unique(switch_console_callback_match_t **matches, const char *new_val)
switch_status_t switch_core_hash_destroy(_Inout_ switch_hash_t **hash)
Destroy an existing hash table.
switch_status_t switch_console_execute(char *xcmd, int rec, switch_stream_handle_t *istream)
void * switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ const char *key)
Retrieve data from a given hash.
#define switch_core_hash_init(_hash)
Definition: switch_core.h:1431
switch_console_callback_match_t * my_matches
switch_status_t switch_console_init(switch_memory_pool_t *pool)
switch_status_t switch_console_add_complete_func(const char *name, switch_console_complete_callback_t cb)
switch_status_t switch_console_list_uuid(const char *line, const char *cursor, switch_console_callback_match_t **matches)
void switch_console_sort_matches(switch_console_callback_match_t *matches)
switch_status_t switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data)
Enumerates a list of all modules discovered in a directory.
unsigned int switch_separate_string_string(char *buf, char *delim, _Post_count_(return) char **array, unsigned int arraylen)
switch_status_t switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
Execute a registered API command.
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
switch_memory_pool_t * pool
static int comp_callback(void *pArg, int argc, char **argv, char **columnNames)
switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt,...) PRINTF_FUNCTION(4
Add a header to an event.
Representation of an event.
Definition: switch_event.h:80
void switch_console_printf(switch_text_channel_t channel, const char *file, const char *func, int line, const char *fmt,...)
Simple Console.
struct switch_console_callback_match_node * head
switch_status_t switch_time_exp_lt(switch_time_exp_t *result, switch_time_t input)
Definition: switch_apr.c:346
switch_status_t(* switch_console_complete_callback_t)(const char *, const char *, switch_console_callback_match_t **matches)
FILE * out
A representation of an XML tree.
Definition: switch_xml.h:79
switch_status_t switch_console_list_interfaces(const char *line, const char *cursor, switch_console_callback_match_t **matches)
void switch_console_free_matches(switch_console_callback_match_t **matches)
switch_status_t switch_console_run_complete_func(const char *func, const char *line, const char *last_word, switch_console_callback_match_t **matches)
switch_xml_t switch_xml_set_txt_d(switch_xml_t xml, const char *txt)
wrapper for switch_xml_set_txt() that strdup()s txt \ sets the character content for the given tag an...
Definition: switch_xml.c:3005
switch_status_t switch_strftime_nocheck(char *s, switch_size_t *retsize, switch_size_t max, const char *format, switch_time_exp_t *tm)
Definition: switch_apr.c:202
struct switch_console_callback_match_node * end
pack cur
static switch_thread_t * thread
Definition: switch_log.c:486
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
uint32_t switch_core_flag_t
Definition: switch_types.h:395
void switch_console_save_history(void)
switch_status_t switch_console_del_complete_func(const char *name)
switch_status_t switch_stream_write_file_contents(switch_stream_handle_t *stream, const char *path)
switch_status_t switch_cache_db_execute_sql_callback(switch_cache_db_handle_t *dbh, const char *sql, switch_core_db_callback_func_t callback, void *pdata, char **err)
Executes the sql and uses callback for row-by-row processing.
#define end_of_p(_s)
Definition: switch_utils.h:686
#define zstr(x)
Definition: switch_utils.h:314
int cJSON_bool fmt
Definition: switch_cJSON.h:150
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
void switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh)
Returns the handle to the pool, handle is NOT available to other threads until the allocating thread ...
switch_hash_t * func_hash
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
switch_status_t switch_threadattr_detach_set(switch_threadattr_t *attr, int32_t on)
Definition: switch_apr.c:678
switch_xml_t next
Definition: switch_xml.h:91
switch_byte_t switch_byte_t * buf
switch_status_t switch_console_set_alias(const char *string)
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_core_flag_t switch_core_flags(void)
return core flags
Definition: switch_core.c:2988
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_zmalloc(ptr, len)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_stream_handle_t * stream
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
static char * console_fnkeys[12]
#define SWITCH_CHANNEL_LOG_CLEAN
static int uuid_callback(void *pArg, int argc, char **argv, char **columnNames)
uintptr_t switch_size_t
static struct @2 globals
static int alias_callback(void *pArg, int argc, char **argv, char **columnNames)
int switch_vasprintf(_Out_opt_ char **buf, _In_z_ _Printf_format_string_ const char *format, _In_ va_list ap)
FILE * switch_core_data_channel(switch_text_channel_t channel)
Retrieve a FILE stream of a given text channel name.
Definition: switch_core.c:286
switch_size_t switch_fp_read_dline(FILE *fd, char **buf, switch_size_t *len)
Definition: switch_utils.c:892
void switch_cond_next(void)
Definition: switch_time.c:658
switch_status_t switch_console_stream_write(switch_stream_handle_t *handle, const char *fmt,...)
#define SWITCH_STANDARD_STREAM(s)
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
static int modulename_callback(void *pArg, const char *module_name)
switch_status_t switch_cache_db_persistant_execute(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries)
static int32_t running
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_status_t switch_console_list_available_modules(const char *line, const char *cursor, switch_console_callback_match_t **matches)
#define switch_core_db_handle(_a)
Definition: switch_core.h:2729
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
#define SWITCH_DECLARE_NONSTD(type)
void switch_core_sql_exec(const char *sql)
char partial[512]
switch_stream_handle_write_function_t write_function
switch_status_t
Common return values.
const char *const const char *const path
switch_status_t switch_console_list_loaded_modules(const char *line, const char *cursor, switch_console_callback_match_t **matches)
const cJSON *const target
void switch_console_loop(void)
A simple comand loop that reads input from the terminal.
switch_cache_db_handle_type_t switch_cache_db_get_type(switch_cache_db_handle_t *dbh)
switch_xml_t switch_xml_open_cfg(_In_z_ const char *file_path, _Out_ switch_xml_t *node, _In_opt_ switch_event_t *params)
open a config in the core registry
const char * switch_core_get_hostname(void)
Definition: switch_core.c:356
#define switch_core_hash_insert(_h, _k, _d)
Definition: switch_core.h:1479
#define FALSE
Main Library Header.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:384
static switch_bool_t switch_is_file_path(const char *file)
#define SWITCH_DECLARE(type)
unsigned char switch_console_complete(const char *line, const char *cursor, FILE *console_out, switch_stream_handle_t *stream, switch_xml_t xml)
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
static switch_status_t console_xml_config(void)
switch_status_t switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data)
Enumerates a list of all currently loaded modules.
static int switch_console_process(char *xcmd)
switch_cache_db_handle_type_t switch_core_dbtype(void)
switch_mutex_t * func_mutex
char * key
Definition: switch_msrp.c:64
char * switch_console_expand_alias(char *cmd, char *arg)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:665
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:698
#define CMD_BUFLEN
int count
Definition: switch_cJSON.h:204
FILE * switch_core_get_console(void)
Get the output console.
Definition: switch_core.c:253
struct fspr_pool_t switch_memory_pool_t
const char *const name
Definition: switch_cJSON.h:250
#define TRUE
int32_t switch_core_session_ctl(switch_session_ctl_t cmd, void *val)
send a control message to the core
Definition: switch_core.c:2651
#define switch_assert(expr)
struct fspr_thread_t switch_thread_t
Definition: switch_apr.h:941
const char * switch_cut_path(const char *in)
Create a pointer to the file name in a given file path eliminating the directory name.
char last[512]
void switch_console_push_match(switch_console_callback_match_t **matches, const char *new_val)
switch_xml_t xml
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
memset(buf, 0, buflen)
char * switch_vmprintf(const char *zFormat, va_list ap)
struct switch_console_callback_match_node * next
switch_status_t switch_console_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen)