Wed Jan 8 2020 09:49:42

Asterisk developer's documentation


asterisk.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2013, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 
20 /* Doxygenified Copyright Header */
21 /*!
22  * \mainpage Asterisk -- The Open Source Telephony Project
23  *
24  * \par Developer Documentation for Asterisk
25  *
26  * This is the main developer documentation for Asterisk. It is
27  * generated by running "make progdocs" from the Asterisk source tree.
28  *
29  * In addition to the information available on the Asterisk source code,
30  * please see the appendices for information on coding guidelines,
31  * release management, commit policies, and more.
32  *
33  * \arg \ref AsteriskArchitecture
34  *
35  * \par Additional documentation
36  * \arg \ref Licensing
37  * \arg \ref DevDoc
38  * \arg \ref ConfigFiles
39  *
40  * \section copyright Copyright and Author
41  *
42  * Copyright (C) 1999 - 2013, Digium, Inc.
43  * Asterisk is a <a href="http://www.digium.com/en/company/view-policy.php?id=Trademark-Policy">registered trademark</a>
44  * of <a rel="nofollow" href="http://www.digium.com">Digium, Inc</a>.
45  *
46  * \author Mark Spencer <markster@digium.com>
47  * Also see \ref AstCREDITS
48  *
49  * See http://www.asterisk.org for more information about
50  * the Asterisk project. Please do not directly contact
51  * any of the maintainers of this project for assistance;
52  * the project provides a web site, mailing lists, and IRC
53  * channels for your use.
54  */
55 
56 /*! \file
57  \brief Top level source file for Asterisk - the Open Source PBX. Implementation
58  of PBX core functions and CLI interface.
59 
60  */
61 
62 /*** MODULEINFO
63  <support_level>core</support_level>
64  ***/
65 
66 #include "asterisk.h"
67 
68 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 415463 $")
69 
70 #include "asterisk/_private.h"
71 
72 #undef sched_setscheduler
73 #undef setpriority
74 #include <sys/time.h>
75 #include <fcntl.h>
76 #include <signal.h>
77 #include <sched.h>
78 #include <sys/un.h>
79 #include <sys/wait.h>
80 #include <ctype.h>
81 #include <sys/resource.h>
82 #include <grp.h>
83 #include <pwd.h>
84 #include <sys/stat.h>
85 #if defined(HAVE_SYSINFO)
86 #include <sys/sysinfo.h>
87 #elif defined(HAVE_SYSCTL)
88 #include <sys/param.h>
89 #include <sys/sysctl.h>
90 #if !defined(__OpenBSD__)
91 #include <sys/vmmeter.h>
92 #if defined(__FreeBSD__)
93 #include <vm/vm_param.h>
94 #endif
95 #endif
96 #if defined(HAVE_SWAPCTL)
97 #include <sys/swap.h>
98 #endif
99 #endif
100 #include <regex.h>
101 
102 #if defined(SOLARIS)
103 int daemon(int, int); /* defined in libresolv of all places */
104 #include <sys/loadavg.h>
105 #endif
106 
107 #ifdef linux
108 #include <sys/prctl.h>
109 #ifdef HAVE_CAP
110 #include <sys/capability.h>
111 #endif /* HAVE_CAP */
112 #endif /* linux */
113 
114 #include "asterisk/paths.h" /* we define here the variables so better agree on the prototype */
115 #include "asterisk/network.h"
116 #include "asterisk/cli.h"
117 #include "asterisk/channel.h"
118 #include "asterisk/features.h"
119 #include "asterisk/ulaw.h"
120 #include "asterisk/alaw.h"
121 #include "asterisk/callerid.h"
122 #include "asterisk/image.h"
123 #include "asterisk/tdd.h"
124 #include "asterisk/term.h"
125 #include "asterisk/manager.h"
126 #include "asterisk/cdr.h"
127 #include "asterisk/cel.h"
128 #include "asterisk/pbx.h"
129 #include "asterisk/enum.h"
130 #include "asterisk/http.h"
131 #include "asterisk/udptl.h"
132 #include "asterisk/app.h"
133 #include "asterisk/lock.h"
134 #include "asterisk/utils.h"
135 #include "asterisk/file.h"
136 #include "asterisk/io.h"
137 #include "editline/histedit.h"
138 #include "asterisk/config.h"
139 #include "asterisk/ast_version.h"
140 #include "asterisk/linkedlists.h"
141 #include "asterisk/devicestate.h"
142 #include "asterisk/module.h"
143 #include "asterisk/dsp.h"
144 #include "asterisk/buildinfo.h"
145 #include "asterisk/xmldoc.h"
146 #include "asterisk/poll-compat.h"
147 #include "asterisk/ccss.h"
148 #include "asterisk/test.h"
149 #include "asterisk/aoc.h"
150 
151 #include "../defaults.h"
152 
153 #ifndef AF_LOCAL
154 #define AF_LOCAL AF_UNIX
155 #define PF_LOCAL PF_UNIX
156 #endif
157 
158 #define AST_MAX_CONNECTS 128
159 #define NUM_MSGS 64
160 
161 /*! \brief Welcome message when starting a CLI interface */
162 #define WELCOME_MESSAGE \
163  ast_verbose("Asterisk %s, Copyright (C) 1999 - 2013 Digium, Inc. and others.\n" \
164  "Created by Mark Spencer <markster@digium.com>\n" \
165  "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
166  "This is free software, with components licensed under the GNU General Public\n" \
167  "License version 2 and other licenses; you are welcome to redistribute it under\n" \
168  "certain conditions. Type 'core show license' for details.\n" \
169  "=========================================================================\n", ast_get_version()) \
170 
171 /*! \defgroup main_options Main Configuration Options
172  * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
173  * \arg \ref Config_ast "asterisk.conf"
174  * \note Some of them can be changed in the CLI
175  */
176 /*! @{ */
177 
179 struct ast_flags ast_compat = { 0 };
180 
181 int option_verbose; /*!< Verbosity level */
182 int option_debug; /*!< Debug level */
183 double option_maxload; /*!< Max load avg on system */
184 int option_maxcalls; /*!< Max number of active calls */
185 int option_maxfiles; /*!< Max number of open file handles (files, sockets) */
186 #if defined(HAVE_SYSINFO)
187 long option_minmemfree; /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
188 #endif
189 
190 /*! @} */
191 
193 
194 /* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
196 
197 static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
198 static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
200 struct console {
201  int fd; /*!< File descriptor */
202  int p[2]; /*!< Pipe */
203  pthread_t t; /*!< Thread of handler */
204  int mute; /*!< Is the console muted for logs */
205  int uid; /*!< Remote user ID. */
206  int gid; /*!< Remote group ID. */
207  int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */
208 };
209 
210 struct ast_atexit {
211  void (*func)(void);
214 };
215 
217 
218 struct timeval ast_startuptime;
219 struct timeval ast_lastreloadtime;
220 
221 static History *el_hist;
222 static EditLine *el;
223 static char *remotehostname;
224 
226 
228 
229 static int ast_el_add_history(char *);
230 static int ast_el_read_history(char *);
231 static int ast_el_write_history(char *);
232 
233 struct _cfg_paths {
234  char config_dir[PATH_MAX];
235  char module_dir[PATH_MAX];
236  char spool_dir[PATH_MAX];
237  char monitor_dir[PATH_MAX];
238  char var_dir[PATH_MAX];
239  char data_dir[PATH_MAX];
240  char log_dir[PATH_MAX];
241  char agi_dir[PATH_MAX];
242  char run_dir[PATH_MAX];
243  char key_dir[PATH_MAX];
244 
245  char config_file[PATH_MAX];
246  char db_path[PATH_MAX];
247  char pid_path[PATH_MAX];
248  char socket_path[PATH_MAX];
249  char run_user[PATH_MAX];
250  char run_group[PATH_MAX];
251  char system_name[128];
252 };
253 
254 static struct _cfg_paths cfg_paths;
255 
267 
274 
275 static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
276 static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
277 static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
278 static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
279 
280 extern unsigned int ast_FD_SETSIZE;
281 
282 static char *_argv[256];
283 typedef enum {
286  /* Valid values for quit_handler niceness below: */
293 static int restartnow;
294 static pthread_t consolethread = AST_PTHREADT_NULL;
295 static pthread_t mon_sig_flags;
296 static int canary_pid = 0;
297 static char canary_filename[128];
298 static int multi_thread_safe;
299 
300 static char randompool[256];
301 
302 static int sig_alert_pipe[2] = { -1, -1 };
303 static struct {
304  unsigned int need_reload:1;
305  unsigned int need_quit:1;
306  unsigned int need_quit_handler:1;
307 } sig_flags;
308 
309 #if !defined(LOW_MEMORY)
310 struct file_version {
312  const char *file;
313  char *version;
314 };
315 
317 
318 void ast_register_file_version(const char *file, const char *version)
319 {
320  struct file_version *new;
321  char *work;
322  size_t version_length;
323 
324  work = ast_strdupa(version);
325  work = ast_strip(ast_strip_quoted(work, "$", "$"));
326  version_length = strlen(work) + 1;
327 
328  if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
329  return;
330 
331  new->file = file;
332  new->version = (char *) new + sizeof(*new);
333  memcpy(new->version, work, version_length);
337 }
338 
339 void ast_unregister_file_version(const char *file)
340 {
341  struct file_version *find;
342 
345  if (!strcasecmp(find->file, file)) {
347  break;
348  }
349  }
352 
353  if (find)
354  ast_free(find);
355 }
356 
357 char *ast_complete_source_filename(const char *partial, int n)
358 {
359  struct file_version *find;
360  size_t len = strlen(partial);
361  int count = 0;
362  char *res = NULL;
363 
366  if (!strncasecmp(find->file, partial, len) && ++count > n) {
367  res = ast_strdup(find->file);
368  break;
369  }
370  }
372  return res;
373 }
374 
375 /*! \brief Find version for given module name */
376 const char *ast_file_version_find(const char *file)
377 {
378  struct file_version *iterator;
379 
381  AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
382  if (!strcasecmp(iterator->file, file))
383  break;
384  }
386  if (iterator)
387  return iterator->version;
388  return NULL;
389 }
390 
391 
392 
395  char *name;
396  pthread_t id;
397 };
398 
400 
402 {
403  struct thread_list_t *new = ast_calloc(1, sizeof(*new));
404 
405  if (!new)
406  return;
407 
409  new->id = pthread_self();
410  new->name = name; /* steal the allocated memory for the thread name */
414 }
415 
416 void ast_unregister_thread(void *id)
417 {
418  struct thread_list_t *x;
419 
422  if ((void *) x->id == id) {
424  break;
425  }
426  }
429  if (x) {
430  ast_free(x->name);
431  ast_free(x);
432  }
433 }
434 
435 /*! \brief Give an overview of core settings */
436 static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
437 {
438  char buf[BUFSIZ];
439  struct ast_tm tm;
440  char eid_str[128];
441 
442  switch (cmd) {
443  case CLI_INIT:
444  e->command = "core show settings";
445  e->usage = "Usage: core show settings\n"
446  " Show core misc settings";
447  return NULL;
448  case CLI_GENERATE:
449  return NULL;
450  }
451 
452  ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
453 
454  ast_cli(a->fd, "\nPBX Core settings\n");
455  ast_cli(a->fd, "-----------------\n");
456  ast_cli(a->fd, " Version: %s\n", ast_get_version());
457  ast_cli(a->fd, " Build Options: %s\n", S_OR(AST_BUILDOPTS, "(none)"));
458  if (option_maxcalls)
459  ast_cli(a->fd, " Maximum calls: %d (Current %d)\n", option_maxcalls, ast_active_channels());
460  else
461  ast_cli(a->fd, " Maximum calls: Not set\n");
462  if (option_maxfiles)
463  ast_cli(a->fd, " Maximum open file handles: %d\n", option_maxfiles);
464  else
465  ast_cli(a->fd, " Maximum open file handles: Not set\n");
466  ast_cli(a->fd, " Verbosity: %d\n", option_verbose);
467  ast_cli(a->fd, " Debug level: %d\n", option_debug);
468  ast_cli(a->fd, " Maximum load average: %lf\n", option_maxload);
469 #if defined(HAVE_SYSINFO)
470  ast_cli(a->fd, " Minimum free memory: %ld MB\n", option_minmemfree);
471 #endif
472  if (ast_localtime(&ast_startuptime, &tm, NULL)) {
473  ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
474  ast_cli(a->fd, " Startup time: %s\n", buf);
475  }
476  if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
477  ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
478  ast_cli(a->fd, " Last reload time: %s\n", buf);
479  }
480  ast_cli(a->fd, " System: %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
481  ast_cli(a->fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
482  ast_cli(a->fd, " Entity ID: %s\n", eid_str);
483  ast_cli(a->fd, " Default language: %s\n", defaultlanguage);
484  ast_cli(a->fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
485  ast_cli(a->fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
486  ast_cli(a->fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
487  ast_cli(a->fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
488  ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
489  ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
490  struct rlimit rlim;
491  if (!getrlimit(RLIMIT_NOFILE, &rlim))
492  ast_cli(a->fd, " Current file desc. limits: current: %i max: %i\n", rlim.rlim_cur, rlim.rlim_max);
493 
494  ast_cli(a->fd, "\n* Subsystems\n");
495  ast_cli(a->fd, " -------------\n");
496  ast_cli(a->fd, " Manager (AMI): %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
497  ast_cli(a->fd, " Web Manager (AMI/HTTP): %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
498  ast_cli(a->fd, " Call data records: %s\n", check_cdr_enabled() ? "Enabled" : "Disabled");
499  ast_cli(a->fd, " Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
500 
501  /*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
502 
503  ast_cli(a->fd, "\n* Directories\n");
504  ast_cli(a->fd, " -------------\n");
505  ast_cli(a->fd, " Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
506  ast_cli(a->fd, " Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
507  ast_cli(a->fd, " Module directory: %s\n", ast_config_AST_MODULE_DIR);
508  ast_cli(a->fd, " Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
509  ast_cli(a->fd, " Log directory: %s\n", ast_config_AST_LOG_DIR);
510  ast_cli(a->fd, " Run/Sockets directory: %s\n", ast_config_AST_RUN_DIR);
511  ast_cli(a->fd, " PID file: %s\n", ast_config_AST_PID);
512  ast_cli(a->fd, " VarLib directory: %s\n", ast_config_AST_VAR_DIR);
513  ast_cli(a->fd, " Data directory: %s\n", ast_config_AST_DATA_DIR);
514  ast_cli(a->fd, " ASTDB: %s\n", ast_config_AST_DB);
515  ast_cli(a->fd, " IAX2 Keys directory: %s\n", ast_config_AST_KEY_DIR);
516  ast_cli(a->fd, " AGI Scripts directory: %s\n", ast_config_AST_AGI_DIR);
517  ast_cli(a->fd, "\n\n");
518  return CLI_SUCCESS;
519 }
520 
521 static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
522 {
523  int count = 0;
524  struct thread_list_t *cur;
525  switch (cmd) {
526  case CLI_INIT:
527  e->command = "core show threads";
528  e->usage =
529  "Usage: core show threads\n"
530  " List threads currently active in the system.\n";
531  return NULL;
532  case CLI_GENERATE:
533  return NULL;
534  }
535 
538  ast_cli(a->fd, "%p %s\n", (void *)cur->id, cur->name);
539  count++;
540  }
542  ast_cli(a->fd, "%d threads listed.\n", count);
543  return CLI_SUCCESS;
544 }
545 
546 #if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
547 /*
548  * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
549  * to be based on the new swapctl(2) system call.
550  */
551 static int swapmode(int *used, int *total)
552 {
553  struct swapent *swdev;
554  int nswap, rnswap, i;
555 
556  nswap = swapctl(SWAP_NSWAP, 0, 0);
557  if (nswap == 0)
558  return 0;
559 
560  swdev = ast_calloc(nswap, sizeof(*swdev));
561  if (swdev == NULL)
562  return 0;
563 
564  rnswap = swapctl(SWAP_STATS, swdev, nswap);
565  if (rnswap == -1) {
566  ast_free(swdev);
567  return 0;
568  }
569 
570  /* if rnswap != nswap, then what? */
571 
572  /* Total things up */
573  *total = *used = 0;
574  for (i = 0; i < nswap; i++) {
575  if (swdev[i].se_flags & SWF_ENABLE) {
576  *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
577  *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
578  }
579  }
580  ast_free(swdev);
581  return 1;
582 }
583 #elif defined(HAVE_SYSCTL) && !defined(HAVE_SYSINFO)
584 static int swapmode(int *used, int *total)
585 {
586  *used = *total = 0;
587  return 1;
588 }
589 #endif
590 
591 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
592 /*! \brief Give an overview of system statistics */
593 static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
594 {
595  uint64_t physmem, freeram;
596  uint64_t freeswap = 0;
597  int nprocs = 0;
598  long uptime = 0;
599  int totalswap = 0;
600 #if defined(HAVE_SYSINFO)
601  struct sysinfo sys_info;
602  sysinfo(&sys_info);
603  uptime = sys_info.uptime / 3600;
604  physmem = sys_info.totalram * sys_info.mem_unit;
605  freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
606  totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
607  freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
608  nprocs = sys_info.procs;
609 #elif defined(HAVE_SYSCTL)
610  static int pageshift;
611  struct vmtotal vmtotal;
612  struct timeval boottime;
613  time_t now;
614  int mib[2], pagesize, usedswap = 0;
615  size_t len;
616  /* calculate the uptime by looking at boottime */
617  time(&now);
618  mib[0] = CTL_KERN;
619  mib[1] = KERN_BOOTTIME;
620  len = sizeof(boottime);
621  if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
622  uptime = now - boottime.tv_sec;
623  }
624  uptime = uptime/3600;
625  /* grab total physical memory */
626  mib[0] = CTL_HW;
627 #if defined(HW_PHYSMEM64)
628  mib[1] = HW_PHYSMEM64;
629 #else
630  mib[1] = HW_PHYSMEM;
631 #endif
632  len = sizeof(physmem);
633  sysctl(mib, 2, &physmem, &len, NULL, 0);
634 
635  pagesize = getpagesize();
636  pageshift = 0;
637  while (pagesize > 1) {
638  pageshift++;
639  pagesize >>= 1;
640  }
641 
642  /* we only need the amount of log(2)1024 for our conversion */
643  pageshift -= 10;
644 
645  /* grab vm totals */
646  mib[0] = CTL_VM;
647  mib[1] = VM_METER;
648  len = sizeof(vmtotal);
649  sysctl(mib, 2, &vmtotal, &len, NULL, 0);
650  freeram = (vmtotal.t_free << pageshift);
651  /* generate swap usage and totals */
652  swapmode(&usedswap, &totalswap);
653  freeswap = (totalswap - usedswap);
654  /* grab number of processes */
655 #if defined(__OpenBSD__)
656  mib[0] = CTL_KERN;
657  mib[1] = KERN_NPROCS;
658  len = sizeof(nprocs);
659  sysctl(mib, 2, &nprocs, &len, NULL, 0);
660 #endif
661 #endif
662 
663  switch (cmd) {
664  case CLI_INIT:
665  e->command = "core show sysinfo";
666  e->usage =
667  "Usage: core show sysinfo\n"
668  " List current system information.\n";
669  return NULL;
670  case CLI_GENERATE:
671  return NULL;
672  }
673 
674  ast_cli(a->fd, "\nSystem Statistics\n");
675  ast_cli(a->fd, "-----------------\n");
676  ast_cli(a->fd, " System Uptime: %ld hours\n", uptime);
677  ast_cli(a->fd, " Total RAM: %" PRIu64 " KiB\n", physmem / 1024);
678  ast_cli(a->fd, " Free RAM: %" PRIu64 " KiB\n", freeram);
679 #if defined(HAVE_SYSINFO)
680  ast_cli(a->fd, " Buffer RAM: %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
681 #endif
682 #if defined (HAVE_SYSCTL) || defined(HAVE_SWAPCTL)
683  ast_cli(a->fd, " Total Swap Space: %d KiB\n", totalswap);
684  ast_cli(a->fd, " Free Swap Space: %" PRIu64 " KiB\n\n", freeswap);
685 #endif
686  ast_cli(a->fd, " Number of Processes: %d \n\n", nprocs);
687  return CLI_SUCCESS;
688 }
689 #endif
690 
692  const char *name;
693  uint64_t scale; /* if non-zero, values are scaled by this */
694  int64_t mark;
695  int64_t value;
696  int64_t events;
697 };
698 
699 struct profile_data {
700  int entries;
701  int max_size;
702  struct profile_entry e[0];
703 };
704 
705 static struct profile_data *prof_data;
706 
707 /*! \brief allocates a counter with a given name and scale.
708  * \return Returns the identifier of the counter.
709  */
710 int ast_add_profile(const char *name, uint64_t scale)
711 {
712  int l = sizeof(struct profile_data);
713  int n = 10; /* default entries */
714 
715  if (prof_data == NULL) {
716  prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
717  if (prof_data == NULL)
718  return -1;
719  prof_data->entries = 0;
720  prof_data->max_size = n;
721  }
722  if (prof_data->entries >= prof_data->max_size) {
723  void *p;
724  n = prof_data->max_size + 20;
725  p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
726  if (p == NULL)
727  return -1;
728  prof_data = p;
729  prof_data->max_size = n;
730  }
731  n = prof_data->entries++;
732  prof_data->e[n].name = ast_strdup(name);
733  prof_data->e[n].value = 0;
734  prof_data->e[n].events = 0;
735  prof_data->e[n].mark = 0;
736  prof_data->e[n].scale = scale;
737  return n;
738 }
739 
740 int64_t ast_profile(int i, int64_t delta)
741 {
742  if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
743  return 0;
744  if (prof_data->e[i].scale > 1)
745  delta /= prof_data->e[i].scale;
746  prof_data->e[i].value += delta;
747  prof_data->e[i].events++;
748  return prof_data->e[i].value;
749 }
750 
751 /* The RDTSC instruction was introduced on the Pentium processor and is not
752  * implemented on certain clones, like the Cyrix 586. Hence, the previous
753  * expectation of __i386__ was in error. */
754 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
755 #if defined(__FreeBSD__)
756 #include <machine/cpufunc.h>
757 #elif defined(linux)
758 static __inline uint64_t
759 rdtsc(void)
760 {
761  uint64_t rv;
762 
763  __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
764  return (rv);
765 }
766 #endif
767 #else /* supply a dummy function on other platforms */
768 static __inline uint64_t
769 rdtsc(void)
770 {
771  return 0;
772 }
773 #endif
774 
775 int64_t ast_mark(int i, int startstop)
776 {
777  if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
778  return 0;
779  if (startstop == 1)
780  prof_data->e[i].mark = rdtsc();
781  else {
782  prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
783  if (prof_data->e[i].scale > 1)
784  prof_data->e[i].mark /= prof_data->e[i].scale;
785  prof_data->e[i].value += prof_data->e[i].mark;
786  prof_data->e[i].events++;
787  }
788  return prof_data->e[i].mark;
789 }
790 
791 #define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
792  max = prof_data->entries;\
793  if (a->argc > 3) { /* specific entries */ \
794  if (isdigit(a->argv[3][0])) { \
795  min = atoi(a->argv[3]); \
796  if (a->argc == 5 && strcmp(a->argv[4], "-")) \
797  max = atoi(a->argv[4]); \
798  } else \
799  search = a->argv[3]; \
800  } \
801  if (max > prof_data->entries) \
802  max = prof_data->entries;
803 
804 static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
805 {
806  int i, min, max;
807  const char *search = NULL;
808  switch (cmd) {
809  case CLI_INIT:
810  e->command = "core show profile";
811  e->usage = "Usage: core show profile\n"
812  " show profile information";
813  return NULL;
814  case CLI_GENERATE:
815  return NULL;
816  }
817 
818  if (prof_data == NULL)
819  return 0;
820 
822  ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
824  ast_cli(a->fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
825  "Value", "Average", "Name");
826  for (i = min; i < max; i++) {
827  struct profile_entry *entry = &prof_data->e[i];
828  if (!search || strstr(entry->name, search))
829  ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
830  i,
831  (long)entry->scale,
832  (long)entry->events, (long long)entry->value,
833  (long long)(entry->events ? entry->value / entry->events : entry->value),
834  entry->name);
835  }
836  return CLI_SUCCESS;
837 }
838 
839 static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
840 {
841  int i, min, max;
842  const char *search = NULL;
843  switch (cmd) {
844  case CLI_INIT:
845  e->command = "core clear profile";
846  e->usage = "Usage: core clear profile\n"
847  " clear profile information";
848  return NULL;
849  case CLI_GENERATE:
850  return NULL;
851  }
852 
853  if (prof_data == NULL)
854  return 0;
855 
857  for (i= min; i < max; i++) {
858  if (!search || strstr(prof_data->e[i].name, search)) {
859  prof_data->e[i].value = 0;
860  prof_data->e[i].events = 0;
861  }
862  }
863  return CLI_SUCCESS;
864 }
865 #undef DEFINE_PROFILE_MIN_MAX_VALUES
866 
867 /*! \brief CLI command to list module versions */
868 static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
869 {
870 #define FORMAT "%-25.25s %-40.40s\n"
871  struct file_version *iterator;
872  regex_t regexbuf;
873  int havepattern = 0;
874  int havename = 0;
875  int count_files = 0;
876  char *ret = NULL;
877  int matchlen, which = 0;
878  struct file_version *find;
879 
880  switch (cmd) {
881  case CLI_INIT:
882  e->command = "core show file version [like]";
883  e->usage =
884  "Usage: core show file version [like <pattern>]\n"
885  " Lists the revision numbers of the files used to build this copy of Asterisk.\n"
886  " Optional regular expression pattern is used to filter the file list.\n";
887  return NULL;
888  case CLI_GENERATE:
889  matchlen = strlen(a->word);
890  if (a->pos != 3)
891  return NULL;
894  if (!strncasecmp(a->word, find->file, matchlen) && ++which > a->n) {
895  ret = ast_strdup(find->file);
896  break;
897  }
898  }
900  return ret;
901  }
902 
903 
904  switch (a->argc) {
905  case 6:
906  if (!strcasecmp(a->argv[4], "like")) {
907  if (regcomp(&regexbuf, a->argv[5], REG_EXTENDED | REG_NOSUB))
908  return CLI_SHOWUSAGE;
909  havepattern = 1;
910  } else
911  return CLI_SHOWUSAGE;
912  break;
913  case 5:
914  havename = 1;
915  break;
916  case 4:
917  break;
918  default:
919  return CLI_SHOWUSAGE;
920  }
921 
922  ast_cli(a->fd, FORMAT, "File", "Revision");
923  ast_cli(a->fd, FORMAT, "----", "--------");
925  AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
926  if (havename && strcasecmp(iterator->file, a->argv[4]))
927  continue;
928 
929  if (havepattern && regexec(&regexbuf, iterator->file, 0, NULL, 0))
930  continue;
931 
932  ast_cli(a->fd, FORMAT, iterator->file, iterator->version);
933  count_files++;
934  if (havename)
935  break;
936  }
938  if (!havename) {
939  ast_cli(a->fd, "%d files listed.\n", count_files);
940  }
941 
942  if (havepattern)
943  regfree(&regexbuf);
944 
945  return CLI_SUCCESS;
946 #undef FORMAT
947 }
948 
949 #endif /* ! LOW_MEMORY */
950 
951 static void ast_run_atexits(int run_cleanups)
952 {
953  struct ast_atexit *ae;
954 
956  while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
957  if (ae->func && (!ae->is_cleanup || run_cleanups)) {
958  ae->func();
959  }
960  ast_free(ae);
961  }
963 }
964 
965 static void __ast_unregister_atexit(void (*func)(void))
966 {
967  struct ast_atexit *ae;
968 
970  if (ae->func == func) {
972  ast_free(ae);
973  break;
974  }
975  }
977 }
978 
979 static int register_atexit(void (*func)(void), int is_cleanup)
980 {
981  struct ast_atexit *ae;
982 
983  ae = ast_calloc(1, sizeof(*ae));
984  if (!ae) {
985  return -1;
986  }
987  ae->func = func;
988  ae->is_cleanup = is_cleanup;
989 
994 
995  return 0;
996 }
997 
998 int ast_register_atexit(void (*func)(void))
999 {
1000  return register_atexit(func, 0);
1001 }
1002 
1003 int ast_register_cleanup(void (*func)(void))
1004 {
1005  return register_atexit(func, 1);
1006 }
1007 
1008 void ast_unregister_atexit(void (*func)(void))
1009 {
1013 }
1014 
1015 /* Sending commands from consoles back to the daemon requires a terminating NULL */
1016 static int fdsend(int fd, const char *s)
1017 {
1018  return write(fd, s, strlen(s) + 1);
1019 }
1020 
1021 /* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
1022 static int fdprint(int fd, const char *s)
1023 {
1024  return write(fd, s, strlen(s));
1025 }
1026 
1027 /*! \brief NULL handler so we can collect the child exit status */
1028 static void _null_sig_handler(int sig)
1029 {
1030 }
1031 
1032 static struct sigaction null_sig_handler = {
1033  .sa_handler = _null_sig_handler,
1034  .sa_flags = SA_RESTART,
1035 };
1036 
1037 static struct sigaction ignore_sig_handler = {
1038  .sa_handler = SIG_IGN,
1039 };
1040 
1042 /*! \brief Keep track of how many threads are currently trying to wait*() on
1043  * a child process */
1044 static unsigned int safe_system_level = 0;
1045 static struct sigaction safe_system_prev_handler;
1046 
1048 {
1049  unsigned int level;
1050 
1052  level = safe_system_level++;
1053 
1054  /* only replace the handler if it has not already been done */
1055  if (level == 0) {
1056  sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1057  }
1058 
1060 }
1061 
1063 {
1064  unsigned int level;
1065 
1067  level = --safe_system_level;
1068 
1069  /* only restore the handler if we are the last one */
1070  if (level == 0) {
1071  sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1072  }
1073 
1075 }
1076 
1077 int ast_safe_system(const char *s)
1078 {
1079  pid_t pid;
1080  int res;
1081  struct rusage rusage;
1082  int status;
1083 
1084 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1086 
1087 #ifdef HAVE_WORKING_FORK
1088  pid = fork();
1089 #else
1090  pid = vfork();
1091 #endif
1092 
1093  if (pid == 0) {
1094 #ifdef HAVE_CAP
1095  cap_t cap = cap_from_text("cap_net_admin-eip");
1096 
1097  if (cap_set_proc(cap)) {
1098  /* Careful with order! Logging cannot happen after we close FDs */
1099  ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
1100  }
1101  cap_free(cap);
1102 #endif
1103 #ifdef HAVE_WORKING_FORK
1105  ast_set_priority(0);
1106  /* Close file descriptors and launch system command */
1107  ast_close_fds_above_n(STDERR_FILENO);
1108 #endif
1109  execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
1110  _exit(1);
1111  } else if (pid > 0) {
1112  for (;;) {
1113  res = wait4(pid, &status, 0, &rusage);
1114  if (res > -1) {
1115  res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1116  break;
1117  } else if (errno != EINTR)
1118  break;
1119  }
1120  } else {
1121  ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
1122  res = -1;
1123  }
1124 
1126 #else /* !defined(HAVE_WORKING_FORK) && !defined(HAVE_WORKING_VFORK) */
1127  res = -1;
1128 #endif
1129 
1130  return res;
1131 }
1132 
1133 /*!
1134  * \brief enable or disable a logging level to a specified console
1135  */
1136 void ast_console_toggle_loglevel(int fd, int level, int state)
1137 {
1138  int x;
1139 
1140  if (level >= NUMLOGLEVELS) {
1141  level = NUMLOGLEVELS - 1;
1142  }
1143 
1144  for (x = 0;x < AST_MAX_CONNECTS; x++) {
1145  if (fd == consoles[x].fd) {
1146  /*
1147  * Since the logging occurs when levels are false, set to
1148  * flipped iinput because this function accepts 0 as off and 1 as on
1149  */
1150  consoles[x].levels[level] = state ? 0 : 1;
1151  return;
1152  }
1153  }
1154 }
1155 
1156 /*!
1157  * \brief mute or unmute a console from logging
1158  */
1159 void ast_console_toggle_mute(int fd, int silent)
1160 {
1161  int x;
1162  for (x = 0;x < AST_MAX_CONNECTS; x++) {
1163  if (fd == consoles[x].fd) {
1164  if (consoles[x].mute) {
1165  consoles[x].mute = 0;
1166  if (!silent)
1167  ast_cli(fd, "Console is not muted anymore.\n");
1168  } else {
1169  consoles[x].mute = 1;
1170  if (!silent)
1171  ast_cli(fd, "Console is muted.\n");
1172  }
1173  return;
1174  }
1175  }
1176  ast_cli(fd, "Couldn't find remote console.\n");
1177 }
1178 
1179 /*!
1180  * \brief log the string to all attached console clients
1181  */
1182 static void ast_network_puts_mutable(const char *string, int level)
1183 {
1184  int x;
1185  for (x = 0;x < AST_MAX_CONNECTS; x++) {
1186  if (consoles[x].mute)
1187  continue;
1188  if (consoles[x].fd > -1) {
1189  if (!consoles[x].levels[level])
1190  fdprint(consoles[x].p[1], string);
1191  }
1192  }
1193 }
1194 
1195 /*!
1196  * \brief log the string to the console, and all attached
1197  * console clients
1198  */
1199 void ast_console_puts_mutable(const char *string, int level)
1200 {
1201  fputs(string, stdout);
1202  fflush(stdout);
1203  ast_network_puts_mutable(string, level);
1204 }
1205 
1206 /*!
1207  * \brief write the string to all attached console clients
1208  */
1209 static void ast_network_puts(const char *string)
1210 {
1211  int x;
1212  for (x = 0; x < AST_MAX_CONNECTS; x++) {
1213  if (consoles[x].fd > -1)
1214  fdprint(consoles[x].p[1], string);
1215  }
1216 }
1217 
1218 /*!
1219  * write the string to the console, and all attached
1220  * console clients
1221  */
1222 void ast_console_puts(const char *string)
1223 {
1224  fputs(string, stdout);
1225  fflush(stdout);
1226  ast_network_puts(string);
1227 }
1228 
1229 static void network_verboser(const char *s)
1230 {
1232 }
1233 
1234 static pthread_t lthread;
1235 
1236 /*!
1237  * \brief read() function supporting the reception of user credentials.
1238  *
1239  * \param fd Socket file descriptor.
1240  * \param buffer Receive buffer.
1241  * \param size 'buffer' size.
1242  * \param con Console structure to set received credentials
1243  * \retval -1 on error
1244  * \retval the number of bytes received on success.
1245  */
1246 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1247 {
1248 #if defined(SO_PEERCRED)
1249 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1250 #define HAVE_STRUCT_UCRED_UID
1251  struct sockpeercred cred;
1252 #else
1253  struct ucred cred;
1254 #endif
1255  socklen_t len = sizeof(cred);
1256 #endif
1257 #if defined(HAVE_GETPEEREID)
1258  uid_t uid;
1259  gid_t gid;
1260 #else
1261  int uid, gid;
1262 #endif
1263  int result;
1264 
1265  result = read(fd, buffer, size);
1266  if (result < 0) {
1267  return result;
1268  }
1269 
1270 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1271  if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1272  return result;
1273  }
1274 #if defined(HAVE_STRUCT_UCRED_UID)
1275  uid = cred.uid;
1276  gid = cred.gid;
1277 #else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1278  uid = cred.cr_uid;
1279  gid = cred.cr_gid;
1280 #endif /* defined(HAVE_STRUCT_UCRED_UID) */
1281 
1282 #elif defined(HAVE_GETPEEREID)
1283  if (getpeereid(fd, &uid, &gid)) {
1284  return result;
1285  }
1286 #else
1287  return result;
1288 #endif
1289  con->uid = uid;
1290  con->gid = gid;
1291 
1292  return result;
1293 }
1294 
1295 static void *netconsole(void *vconsole)
1296 {
1297  struct console *con = vconsole;
1298  char hostname[MAXHOSTNAMELEN] = "";
1299  char inbuf[512];
1300  char outbuf[512];
1301  const char * const end_buf = inbuf + sizeof(inbuf);
1302  char *start_read = inbuf;
1303  int res;
1304  struct pollfd fds[2];
1305 
1306  if (gethostname(hostname, sizeof(hostname)-1))
1307  ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1308  snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1309  fdprint(con->fd, outbuf);
1310  for (;;) {
1311  fds[0].fd = con->fd;
1312  fds[0].events = POLLIN;
1313  fds[0].revents = 0;
1314  fds[1].fd = con->p[0];
1315  fds[1].events = POLLIN;
1316  fds[1].revents = 0;
1317 
1318  res = ast_poll(fds, 2, -1);
1319  if (res < 0) {
1320  if (errno != EINTR)
1321  ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1322  continue;
1323  }
1324  if (fds[0].revents) {
1325  int cmds_read, bytes_read;
1326  if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) {
1327  break;
1328  }
1329  /* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */
1330  if (strncmp(inbuf, "cli quit after ", 15) == 0) {
1331  ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15);
1332  break;
1333  }
1334  /* ast_cli_command_multiple_full will only process individual commands terminated by a
1335  * NULL and not trailing partial commands. */
1336  if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) {
1337  /* No commands were read. We either have a short read on the first command
1338  * with space left, or a command that is too long */
1339  if (start_read + bytes_read < end_buf) {
1340  start_read += bytes_read;
1341  } else {
1342  ast_log(LOG_ERROR, "Command too long! Skipping\n");
1343  start_read = inbuf;
1344  }
1345  continue;
1346  }
1347  if (start_read[bytes_read - 1] == '\0') {
1348  /* The read ended on a command boundary, start reading again at the head of inbuf */
1349  start_read = inbuf;
1350  continue;
1351  }
1352  /* If we get this far, we have left over characters that have not been processed.
1353  * Advance to the character after the last command read by ast_cli_command_multiple_full.
1354  * We are guaranteed to have at least cmds_read NULLs */
1355  while (cmds_read-- && (start_read = strchr(start_read, '\0'))) {
1356  start_read++;
1357  }
1358  memmove(inbuf, start_read, end_buf - start_read);
1359  start_read = end_buf - start_read + inbuf;
1360  }
1361  if (fds[1].revents) {
1362  res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con);
1363  if (res < 1) {
1364  ast_log(LOG_ERROR, "read returned %d\n", res);
1365  break;
1366  }
1367  res = write(con->fd, outbuf, res);
1368  if (res < 1)
1369  break;
1370  }
1371  }
1372  if (!ast_opt_hide_connect) {
1373  ast_verb(3, "Remote UNIX connection disconnected\n");
1374  }
1375  close(con->fd);
1376  close(con->p[0]);
1377  close(con->p[1]);
1378  con->fd = -1;
1379 
1380  return NULL;
1381 }
1382 
1383 static void *listener(void *unused)
1384 {
1385  struct sockaddr_un sunaddr;
1386  int s;
1387  socklen_t len;
1388  int x;
1389  int flags;
1390  struct pollfd fds[1];
1391  for (;;) {
1392  if (ast_socket < 0)
1393  return NULL;
1394  fds[0].fd = ast_socket;
1395  fds[0].events = POLLIN;
1396  s = ast_poll(fds, 1, -1);
1397  pthread_testcancel();
1398  if (s < 0) {
1399  if (errno != EINTR)
1400  ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1401  continue;
1402  }
1403  len = sizeof(sunaddr);
1404  s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1405  if (s < 0) {
1406  if (errno != EINTR)
1407  ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1408  } else {
1409 #if !defined(SO_PASSCRED)
1410  {
1411 #else
1412  int sckopt = 1;
1413  /* turn on socket credentials passing. */
1414  if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1415  ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1416  } else {
1417 #endif
1418  for (x = 0; x < AST_MAX_CONNECTS; x++) {
1419  if (consoles[x].fd >= 0) {
1420  continue;
1421  }
1422  if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1423  ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1424  consoles[x].fd = -1;
1425  fdprint(s, "Server failed to create pipe\n");
1426  close(s);
1427  break;
1428  }
1429  flags = fcntl(consoles[x].p[1], F_GETFL);
1430  fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
1431  consoles[x].fd = s;
1432  consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1433  /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1434  to know if the user didn't send the credentials. */
1435  consoles[x].uid = -2;
1436  consoles[x].gid = -2;
1438  ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1439  close(consoles[x].p[0]);
1440  close(consoles[x].p[1]);
1441  consoles[x].fd = -1;
1442  fdprint(s, "Server failed to spawn thread\n");
1443  close(s);
1444  }
1445  break;
1446  }
1447  if (x >= AST_MAX_CONNECTS) {
1448  fdprint(s, "No more connections allowed\n");
1449  ast_log(LOG_WARNING, "No more connections allowed\n");
1450  close(s);
1451  } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1452  ast_verb(3, "Remote UNIX connection\n");
1453  }
1454  }
1455  }
1456  }
1457  return NULL;
1458 }
1459 
1460 static int ast_makesocket(void)
1461 {
1462  struct sockaddr_un sunaddr;
1463  int res;
1464  int x;
1465  uid_t uid = -1;
1466  gid_t gid = -1;
1467 
1468  for (x = 0; x < AST_MAX_CONNECTS; x++)
1469  consoles[x].fd = -1;
1470  unlink(ast_config_AST_SOCKET);
1471  ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1472  if (ast_socket < 0) {
1473  ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1474  return -1;
1475  }
1476  memset(&sunaddr, 0, sizeof(sunaddr));
1477  sunaddr.sun_family = AF_LOCAL;
1478  ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1479  res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1480  if (res) {
1481  ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1482  close(ast_socket);
1483  ast_socket = -1;
1484  return -1;
1485  }
1486  res = listen(ast_socket, 2);
1487  if (res < 0) {
1488  ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1489  close(ast_socket);
1490  ast_socket = -1;
1491  return -1;
1492  }
1494  ast_log(LOG_WARNING, "Unable to register network verboser?\n");
1495  }
1496 
1497  if (ast_pthread_create_background(&lthread, NULL, listener, NULL)) {
1498  ast_log(LOG_WARNING, "Unable to create listener thread.\n");
1499  close(ast_socket);
1500  return -1;
1501  }
1502 
1504  struct passwd *pw;
1505  if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1506  ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1507  else
1508  uid = pw->pw_uid;
1509  }
1510 
1512  struct group *grp;
1513  if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1514  ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1515  else
1516  gid = grp->gr_gid;
1517  }
1518 
1519  if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1520  ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1521 
1523  unsigned int p1;
1524  mode_t p;
1525  sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1526  p = p1;
1527  if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1528  ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1529  }
1530 
1531  return 0;
1532 }
1533 
1534 static int ast_tryconnect(void)
1535 {
1536  struct sockaddr_un sunaddr;
1537  int res;
1538  ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1539  if (ast_consock < 0) {
1540  fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
1541  return 0;
1542  }
1543  memset(&sunaddr, 0, sizeof(sunaddr));
1544  sunaddr.sun_family = AF_LOCAL;
1545  ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1546  res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1547  if (res) {
1548  close(ast_consock);
1549  ast_consock = -1;
1550  return 0;
1551  } else
1552  return 1;
1553 }
1554 
1555 /*! \brief Urgent handler
1556 
1557  Called by soft_hangup to interrupt the poll, read, or other
1558  system call. We don't actually need to do anything though.
1559  Remember: Cannot EVER ast_log from within a signal handler
1560  */
1561 static void _urg_handler(int num)
1562 {
1563  return;
1564 }
1565 
1566 static struct sigaction urg_handler = {
1567  .sa_handler = _urg_handler,
1568  .sa_flags = SA_RESTART,
1569 };
1570 
1571 static void _hup_handler(int num)
1572 {
1573  int a = 0, save_errno = errno;
1574  if (option_verbose > 1)
1575  printf("Received HUP signal -- Reloading configs\n");
1576  if (restartnow)
1577  execvp(_argv[0], _argv);
1578  sig_flags.need_reload = 1;
1579  if (sig_alert_pipe[1] != -1) {
1580  if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1581  fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1582  }
1583  }
1584  errno = save_errno;
1585 }
1586 
1587 static struct sigaction hup_handler = {
1588  .sa_handler = _hup_handler,
1589  .sa_flags = SA_RESTART,
1590 };
1591 
1592 static void _child_handler(int sig)
1593 {
1594  /* Must not ever ast_log or ast_verbose within signal handler */
1595  int n, status, save_errno = errno;
1596 
1597  /*
1598  * Reap all dead children -- not just one
1599  */
1600  for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
1601  ;
1602  if (n == 0 && option_debug)
1603  printf("Huh? Child handler, but nobody there?\n");
1604  errno = save_errno;
1605 }
1606 
1607 static struct sigaction child_handler = {
1608  .sa_handler = _child_handler,
1609  .sa_flags = SA_RESTART,
1610 };
1611 
1612 /*! \brief Set maximum open files */
1613 static void set_ulimit(int value)
1614 {
1615  struct rlimit l = {0, 0};
1616 
1617  if (value <= 0) {
1618  ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
1619  return;
1620  }
1621 
1622  l.rlim_cur = value;
1623  l.rlim_max = value;
1624 
1625  if (setrlimit(RLIMIT_NOFILE, &l)) {
1626  ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
1627  return;
1628  }
1629 
1630  ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
1631 
1632  return;
1633 }
1634 
1635 /*! \brief Set an X-term or screen title */
1636 static void set_title(char *text)
1637 {
1638  if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1639  fprintf(stdout, "\033]2;%s\007", text);
1640 }
1641 
1642 static void set_icon(char *text)
1643 {
1644  if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1645  fprintf(stdout, "\033]1;%s\007", text);
1646 }
1647 
1648 /*! \brief We set ourselves to a high priority, that we might pre-empt everything
1649  else. If your PBX has heavy activity on it, this is a good thing. */
1650 int ast_set_priority(int pri)
1651 {
1652  struct sched_param sched;
1653  memset(&sched, 0, sizeof(sched));
1654 #ifdef __linux__
1655  if (pri) {
1656  sched.sched_priority = 10;
1657  if (sched_setscheduler(0, SCHED_RR, &sched)) {
1658  ast_log(LOG_WARNING, "Unable to set high priority\n");
1659  return -1;
1660  } else
1661  if (option_verbose)
1662  ast_verbose("Set to realtime thread\n");
1663  } else {
1664  sched.sched_priority = 0;
1665  /* According to the manpage, these parameters can never fail. */
1666  sched_setscheduler(0, SCHED_OTHER, &sched);
1667  }
1668 #else
1669  if (pri) {
1670  if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1671  ast_log(LOG_WARNING, "Unable to set high priority\n");
1672  return -1;
1673  } else
1674  if (option_verbose)
1675  ast_verbose("Set to high priority\n");
1676  } else {
1677  /* According to the manpage, these parameters can never fail. */
1678  setpriority(PRIO_PROCESS, 0, 0);
1679  }
1680 #endif
1681  return 0;
1682 }
1683 
1684 static int can_safely_quit(shutdown_nice_t niceness, int restart);
1685 static void really_quit(int num, shutdown_nice_t niceness, int restart);
1686 
1687 static void quit_handler(int num, shutdown_nice_t niceness, int restart)
1688 {
1689  if (can_safely_quit(niceness, restart)) {
1690  really_quit(num, niceness, restart);
1691  /* No one gets here. */
1692  }
1693  /* It wasn't our time. */
1694 }
1695 
1696 static int can_safely_quit(shutdown_nice_t niceness, int restart)
1697 {
1698  /* Check if someone else isn't already doing this. */
1700  if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
1701  /* Already in progress and other request was less nice. */
1703  ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
1704  return 0;
1705  }
1706  shuttingdown = niceness;
1708 
1709  /* Try to get as many CDRs as possible submitted to the backend engines
1710  * (if in batch mode). really_quit happens to call it again when running
1711  * the atexit handlers, otherwise this would be a bit early. */
1713 
1714  if (niceness == SHUTDOWN_NORMAL) {
1715  time_t s, e;
1716  /* Begin shutdown routine, hanging up active channels */
1717  ast_begin_shutdown(1);
1718  if (option_verbose && ast_opt_console) {
1719  ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
1720  }
1721  time(&s);
1722  for (;;) {
1723  time(&e);
1724  /* Wait up to 15 seconds for all channels to go away */
1725  if ((e - s) > 15 || !ast_undestroyed_channels() || shuttingdown != niceness) {
1726  break;
1727  }
1728  /* Sleep 1/10 of a second */
1729  usleep(100000);
1730  }
1731  } else if (niceness >= SHUTDOWN_NICE) {
1732  if (niceness != SHUTDOWN_REALLY_NICE) {
1733  ast_begin_shutdown(0);
1734  }
1735  if (option_verbose && ast_opt_console) {
1736  ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
1737  }
1738  for (;;) {
1739  if (!ast_undestroyed_channels() || shuttingdown != niceness) {
1740  break;
1741  }
1742  sleep(1);
1743  }
1744  }
1745 
1746  /* Re-acquire lock and check if someone changed the niceness, in which
1747  * case someone else has taken over the shutdown. */
1749  if (shuttingdown != niceness) {
1750  if (shuttingdown == NOT_SHUTTING_DOWN && option_verbose && ast_opt_console) {
1751  ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
1752  }
1754  return 0;
1755  }
1758 
1759  return 1;
1760 }
1761 
1762 /*! Called when exiting is certain. */
1763 static void really_quit(int num, shutdown_nice_t niceness, int restart)
1764 {
1765  int active_channels;
1766  int run_cleanups = niceness >= SHUTDOWN_NICE;
1767 
1768  if (run_cleanups) {
1770  }
1771 
1773  char filename[80] = "";
1774  if (getenv("HOME")) {
1775  snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1776  }
1777  if (!ast_strlen_zero(filename)) {
1778  ast_el_write_history(filename);
1779  }
1780  if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
1781  /* Only end if we are the consolethread, otherwise there's a race with that thread. */
1782  if (el != NULL) {
1783  el_end(el);
1784  }
1785  if (el_hist != NULL) {
1786  history_end(el_hist);
1787  }
1788  } else if (mon_sig_flags == pthread_self()) {
1790  pthread_kill(consolethread, SIGURG);
1791  }
1792  }
1793  }
1794  active_channels = ast_active_channels();
1795  /* The manager event for shutdown must happen prior to ast_run_atexits, as
1796  * the manager interface will dispose of its sessions as part of its
1797  * shutdown.
1798  */
1799  manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\n"
1800  "Restart: %s\r\n",
1801  active_channels ? "Uncleanly" : "Cleanly",
1802  restart ? "True" : "False");
1803  if (option_verbose && ast_opt_console) {
1804  ast_verbose("Asterisk %s ending (%d).\n",
1805  active_channels ? "uncleanly" : "cleanly", num);
1806  }
1807 
1808  if (option_verbose)
1809  ast_verbose("Executing last minute cleanups\n");
1810  ast_run_atexits(run_cleanups);
1811 
1812  ast_debug(1, "Asterisk ending (%d).\n", num);
1813  if (ast_socket > -1) {
1814  pthread_cancel(lthread);
1815  close(ast_socket);
1816  ast_socket = -1;
1817  unlink(ast_config_AST_SOCKET);
1818  pthread_kill(lthread, SIGURG);
1819  pthread_join(lthread, NULL);
1820  }
1821  if (ast_consock > -1)
1822  close(ast_consock);
1823  if (!ast_opt_remote)
1824  unlink(ast_config_AST_PID);
1825  if (sig_alert_pipe[0])
1826  close(sig_alert_pipe[0]);
1827  if (sig_alert_pipe[1])
1828  close(sig_alert_pipe[1]);
1829  printf("%s", term_quit());
1830  if (restart) {
1831  int i;
1832  if (option_verbose || ast_opt_console)
1833  ast_verbose("Preparing for Asterisk restart...\n");
1834  /* Mark all FD's for closing on exec */
1835  for (i = 3; i < 32768; i++) {
1836  fcntl(i, F_SETFD, FD_CLOEXEC);
1837  }
1838  if (option_verbose || ast_opt_console)
1839  ast_verbose("Asterisk is now restarting...\n");
1840  restartnow = 1;
1841 
1842  /* close logger */
1843  close_logger();
1844  clean_time_zones();
1845 
1846  /* If there is a consolethread running send it a SIGHUP
1847  so it can execvp, otherwise we can do it ourselves */
1848  if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
1849  pthread_kill(consolethread, SIGHUP);
1850  /* Give the signal handler some time to complete */
1851  sleep(2);
1852  } else
1853  execvp(_argv[0], _argv);
1854 
1855  } else {
1856  /* close logger */
1857  close_logger();
1858  clean_time_zones();
1859  }
1860 
1861  exit(0);
1862 }
1863 
1864 static void __quit_handler(int num)
1865 {
1866  int a = 0;
1867  sig_flags.need_quit = 1;
1868  if (sig_alert_pipe[1] != -1) {
1869  if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1870  fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
1871  }
1872  }
1873  /* There is no need to restore the signal handler here, since the app
1874  * is going to exit */
1875 }
1876 
1877 static void __remote_quit_handler(int num)
1878 {
1879  sig_flags.need_quit = 1;
1880 }
1881 
1882 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
1883 {
1884  const char *c;
1885 
1886  /* Check for verboser preamble */
1887  if (*s == 127) {
1888  s++;
1889  }
1890 
1891  if (!strncmp(s, cmp, strlen(cmp))) {
1892  c = s + strlen(cmp);
1893  term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
1894  return c;
1895  }
1896  return NULL;
1897 }
1898 
1899 static void console_verboser(const char *s)
1900 {
1901  char tmp[80];
1902  const char *c = NULL;
1903 
1904  if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
1905  (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
1906  (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
1907  (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
1908  fputs(tmp, stdout);
1909  fputs(c, stdout);
1910  } else {
1911  if (*s == 127) {
1912  s++;
1913  }
1914  fputs(s, stdout);
1915  }
1916 
1917  fflush(stdout);
1918 
1919  /* Wake up a poll()ing console */
1921  pthread_kill(consolethread, SIGURG);
1922 }
1923 
1924 static int ast_all_zeros(char *s)
1925 {
1926  while (*s) {
1927  if (*s > 32)
1928  return 0;
1929  s++;
1930  }
1931  return 1;
1932 }
1933 
1934 static void consolehandler(char *s)
1935 {
1936  printf("%s", term_end());
1937  fflush(stdout);
1938 
1939  /* Called when readline data is available */
1940  if (!ast_all_zeros(s))
1941  ast_el_add_history(s);
1942  /* The real handler for bang */
1943  if (s[0] == '!') {
1944  if (s[1])
1945  ast_safe_system(s+1);
1946  else
1947  ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1948  } else
1949  ast_cli_command(STDOUT_FILENO, s);
1950 }
1951 
1952 static int remoteconsolehandler(char *s)
1953 {
1954  int ret = 0;
1955 
1956  /* Called when readline data is available */
1957  if (!ast_all_zeros(s))
1958  ast_el_add_history(s);
1959  /* The real handler for bang */
1960  if (s[0] == '!') {
1961  if (s[1])
1962  ast_safe_system(s+1);
1963  else
1964  ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1965  ret = 1;
1966  }
1967  while (isspace(*s)) {
1968  s++;
1969  }
1970 
1971  if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
1972  (s[4] == '\0' || isspace(s[4]))) {
1973  quit_handler(0, SHUTDOWN_FAST, 0);
1974  ret = 1;
1975  }
1976 
1977  return ret;
1978 }
1979 
1980 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1981 {
1982  switch (cmd) {
1983  case CLI_INIT:
1984  e->command = "core show version";
1985  e->usage =
1986  "Usage: core show version\n"
1987  " Shows Asterisk version information.\n";
1988  return NULL;
1989  case CLI_GENERATE:
1990  return NULL;
1991  }
1992 
1993  if (a->argc != 3)
1994  return CLI_SHOWUSAGE;
1995  ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
1998  return CLI_SUCCESS;
1999 }
2000 
2001 #if 0
2002 static int handle_quit(int fd, int argc, char *argv[])
2003 {
2004  if (argc != 1)
2005  return RESULT_SHOWUSAGE;
2007  return RESULT_SUCCESS;
2008 }
2009 #endif
2010 
2011 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2012 {
2013  switch (cmd) {
2014  case CLI_INIT:
2015  e->command = "core stop now";
2016  e->usage =
2017  "Usage: core stop now\n"
2018  " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
2019  return NULL;
2020  case CLI_GENERATE:
2021  return NULL;
2022  }
2023 
2024  if (a->argc != e->args)
2025  return CLI_SHOWUSAGE;
2026  quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
2027  return CLI_SUCCESS;
2028 }
2029 
2030 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2031 {
2032  switch (cmd) {
2033  case CLI_INIT:
2034  e->command = "core stop gracefully";
2035  e->usage =
2036  "Usage: core stop gracefully\n"
2037  " Causes Asterisk to not accept new calls, and exit when all\n"
2038  " active calls have terminated normally.\n";
2039  return NULL;
2040  case CLI_GENERATE:
2041  return NULL;
2042  }
2043 
2044  if (a->argc != e->args)
2045  return CLI_SHOWUSAGE;
2046  quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
2047  return CLI_SUCCESS;
2048 }
2049 
2050 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2051 {
2052  switch (cmd) {
2053  case CLI_INIT:
2054  e->command = "core stop when convenient";
2055  e->usage =
2056  "Usage: core stop when convenient\n"
2057  " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2058  return NULL;
2059  case CLI_GENERATE:
2060  return NULL;
2061  }
2062 
2063  if (a->argc != e->args)
2064  return CLI_SHOWUSAGE;
2065  ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2066  quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2067  return CLI_SUCCESS;
2068 }
2069 
2070 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2071 {
2072  switch (cmd) {
2073  case CLI_INIT:
2074  e->command = "core restart now";
2075  e->usage =
2076  "Usage: core restart now\n"
2077  " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2078  " restart.\n";
2079  return NULL;
2080  case CLI_GENERATE:
2081  return NULL;
2082  }
2083 
2084  if (a->argc != e->args)
2085  return CLI_SHOWUSAGE;
2086  quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2087  return CLI_SUCCESS;
2088 }
2089 
2090 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2091 {
2092  switch (cmd) {
2093  case CLI_INIT:
2094  e->command = "core restart gracefully";
2095  e->usage =
2096  "Usage: core restart gracefully\n"
2097  " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2098  " restart when all active calls have ended.\n";
2099  return NULL;
2100  case CLI_GENERATE:
2101  return NULL;
2102  }
2103 
2104  if (a->argc != e->args)
2105  return CLI_SHOWUSAGE;
2106  quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2107  return CLI_SUCCESS;
2108 }
2109 
2110 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2111 {
2112  switch (cmd) {
2113  case CLI_INIT:
2114  e->command = "core restart when convenient";
2115  e->usage =
2116  "Usage: core restart when convenient\n"
2117  " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2118  return NULL;
2119  case CLI_GENERATE:
2120  return NULL;
2121  }
2122 
2123  if (a->argc != e->args)
2124  return CLI_SHOWUSAGE;
2125  ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2126  quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2127  return CLI_SUCCESS;
2128 }
2129 
2130 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2131 {
2132  int aborting_shutdown = 0;
2133 
2134  switch (cmd) {
2135  case CLI_INIT:
2136  e->command = "core abort shutdown";
2137  e->usage =
2138  "Usage: core abort shutdown\n"
2139  " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2140  " call operations.\n";
2141  return NULL;
2142  case CLI_GENERATE:
2143  return NULL;
2144  }
2145 
2146  if (a->argc != e->args)
2147  return CLI_SHOWUSAGE;
2148 
2150  if (shuttingdown >= SHUTDOWN_FAST) {
2151  aborting_shutdown = 1;
2153  }
2155 
2156  if (aborting_shutdown) {
2158  }
2159  return CLI_SUCCESS;
2160 }
2161 
2162 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2163 {
2164  switch (cmd) {
2165  case CLI_INIT:
2166  e->command = "!";
2167  e->usage =
2168  "Usage: !<command>\n"
2169  " Executes a given shell command\n";
2170  return NULL;
2171  case CLI_GENERATE:
2172  return NULL;
2173  }
2174 
2175  return CLI_SUCCESS;
2176 }
2177 static const char warranty_lines[] = {
2178  "\n"
2179  " NO WARRANTY\n"
2180  "\n"
2181  "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2182  "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
2183  "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2184  "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2185  "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2186  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
2187  "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
2188  "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2189  "REPAIR OR CORRECTION.\n"
2190  "\n"
2191  "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2192  "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2193  "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2194  "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2195  "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2196  "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2197  "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2198  "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2199  "POSSIBILITY OF SUCH DAMAGES.\n"
2200 };
2201 
2202 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2203 {
2204  switch (cmd) {
2205  case CLI_INIT:
2206  e->command = "core show warranty";
2207  e->usage =
2208  "Usage: core show warranty\n"
2209  " Shows the warranty (if any) for this copy of Asterisk.\n";
2210  return NULL;
2211  case CLI_GENERATE:
2212  return NULL;
2213  }
2214 
2215  ast_cli(a->fd, "%s", warranty_lines);
2216 
2217  return CLI_SUCCESS;
2218 }
2219 
2220 static const char license_lines[] = {
2221  "\n"
2222  "This program is free software; you can redistribute it and/or modify\n"
2223  "it under the terms of the GNU General Public License version 2 as\n"
2224  "published by the Free Software Foundation.\n"
2225  "\n"
2226  "This program also contains components licensed under other licenses.\n"
2227  "They include:\n"
2228  "\n"
2229  "This program is distributed in the hope that it will be useful,\n"
2230  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2231  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2232  "GNU General Public License for more details.\n"
2233  "\n"
2234  "You should have received a copy of the GNU General Public License\n"
2235  "along with this program; if not, write to the Free Software\n"
2236  "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
2237 };
2238 
2239 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2240 {
2241  switch (cmd) {
2242  case CLI_INIT:
2243  e->command = "core show license";
2244  e->usage =
2245  "Usage: core show license\n"
2246  " Shows the license(s) for this copy of Asterisk.\n";
2247  return NULL;
2248  case CLI_GENERATE:
2249  return NULL;
2250  }
2251 
2252  ast_cli(a->fd, "%s", license_lines);
2253 
2254  return CLI_SUCCESS;
2255 }
2256 
2257 #define ASTERISK_PROMPT "*CLI> "
2258 
2259 #define ASTERISK_PROMPT2 "%s*CLI> "
2260 
2261 /*!
2262  * \brief Shutdown Asterisk CLI commands.
2263  *
2264  * \note These CLI commands cannot be unregistered at shutdown
2265  * because one of them is likely the reason for the shutdown.
2266  * The CLI generates a warning if a command is in-use when it is
2267  * unregistered.
2268  */
2270  AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2271  AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2272  AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2273  AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2274  AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2275  AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2276 };
2277 
2278 static struct ast_cli_entry cli_asterisk[] = {
2279  AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2280  AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2281  AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2282  AST_CLI_DEFINE(handle_version, "Display version info"),
2283  AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2284 #if !defined(LOW_MEMORY)
2285  AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
2286  AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2287 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2288  AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2289 #endif
2290  AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2291  AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2292  AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2293 #endif /* ! LOW_MEMORY */
2294 };
2295 
2296 static int ast_el_read_char(EditLine *editline, char *cp)
2297 {
2298  int num_read = 0;
2299  int lastpos = 0;
2300  struct pollfd fds[2];
2301  int res;
2302  int max;
2303 #define EL_BUF_SIZE 512
2304  char buf[EL_BUF_SIZE];
2305 
2306  for (;;) {
2307  max = 1;
2308  fds[0].fd = ast_consock;
2309  fds[0].events = POLLIN;
2310  if (!ast_opt_exec) {
2311  fds[1].fd = STDIN_FILENO;
2312  fds[1].events = POLLIN;
2313  max++;
2314  }
2315  res = ast_poll(fds, max, -1);
2316  if (res < 0) {
2317  if (sig_flags.need_quit || sig_flags.need_quit_handler)
2318  break;
2319  if (errno == EINTR)
2320  continue;
2321  fprintf(stderr, "poll failed: %s\n", strerror(errno));
2322  break;
2323  }
2324 
2325  if (!ast_opt_exec && fds[1].revents) {
2326  num_read = read(STDIN_FILENO, cp, 1);
2327  if (num_read < 1) {
2328  break;
2329  } else
2330  return (num_read);
2331  }
2332  if (fds[0].revents) {
2333  char *tmp;
2334  res = read(ast_consock, buf, sizeof(buf) - 1);
2335  /* if the remote side disappears exit */
2336  if (res < 1) {
2337  fprintf(stderr, "\nDisconnected from Asterisk server\n");
2338  if (!ast_opt_reconnect) {
2339  quit_handler(0, SHUTDOWN_FAST, 0);
2340  } else {
2341  int tries;
2342  int reconnects_per_second = 20;
2343  fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2344  for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2345  if (ast_tryconnect()) {
2346  fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2347  printf("%s", term_quit());
2349  if (!ast_opt_mute)
2350  fdsend(ast_consock, "logger mute silent");
2351  else
2352  printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2353  break;
2354  } else
2355  usleep(1000000 / reconnects_per_second);
2356  }
2357  if (tries >= 30 * reconnects_per_second) {
2358  fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
2359  quit_handler(0, SHUTDOWN_FAST, 0);
2360  }
2361  }
2362  continue;
2363  }
2364 
2365  buf[res] = '\0';
2366 
2367  /* Strip preamble from asynchronous events, too */
2368  for (tmp = buf; *tmp; tmp++) {
2369  if (*tmp == 127) {
2370  memmove(tmp, tmp + 1, strlen(tmp));
2371  tmp--;
2372  res--;
2373  }
2374  }
2375 
2376  /* Write over the CLI prompt */
2377  if (!ast_opt_exec && !lastpos) {
2378  if (write(STDOUT_FILENO, "\r", 5) < 0) {
2379  }
2380  }
2381  if (write(STDOUT_FILENO, buf, res) < 0) {
2382  }
2383  if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
2384  *cp = CC_REFRESH;
2385  return(1);
2386  } else
2387  lastpos = 1;
2388  }
2389  }
2390 
2391  *cp = '\0';
2392  return (0);
2393 }
2394 
2395 static struct ast_str *prompt = NULL;
2396 
2397 static char *cli_prompt(EditLine *editline)
2398 {
2399  char tmp[100];
2400  char *pfmt;
2401  int color_used = 0;
2402  static int cli_prompt_changes = 0;
2403  char term_code[20];
2404  struct passwd *pw;
2405  struct group *gr;
2406 
2407  if (prompt == NULL) {
2408  prompt = ast_str_create(100);
2409  } else if (!cli_prompt_changes) {
2410  return ast_str_buffer(prompt);
2411  } else {
2412  ast_str_reset(prompt);
2413  }
2414 
2415  if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2416  char *t = pfmt;
2417  struct timeval ts = ast_tvnow();
2418  while (*t != '\0') {
2419  if (*t == '%') {
2420  char hostname[MAXHOSTNAMELEN] = "";
2421  int i, which;
2422  struct ast_tm tm = { 0, };
2423  int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2424 
2425  t++;
2426  switch (*t) {
2427  case 'C': /* color */
2428  t++;
2429  if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2430  ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)));
2431  t += i - 1;
2432  } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2433  ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, 0, sizeof(term_code)));
2434  t += i - 1;
2435  }
2436 
2437  /* If the color has been reset correctly, then there's no need to reset it later */
2438  color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2439  break;
2440  case 'd': /* date */
2441  if (ast_localtime(&ts, &tm, NULL)) {
2442  ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2443  ast_str_append(&prompt, 0, "%s", tmp);
2444  cli_prompt_changes++;
2445  }
2446  break;
2447  case 'g': /* group */
2448  if ((gr = getgrgid(getgid()))) {
2449  ast_str_append(&prompt, 0, "%s", gr->gr_name);
2450  }
2451  break;
2452  case 'h': /* hostname */
2453  if (!gethostname(hostname, sizeof(hostname) - 1)) {
2454  ast_str_append(&prompt, 0, "%s", hostname);
2455  } else {
2456  ast_str_append(&prompt, 0, "%s", "localhost");
2457  }
2458  break;
2459  case 'H': /* short hostname */
2460  if (!gethostname(hostname, sizeof(hostname) - 1)) {
2461  char *dotptr;
2462  if ((dotptr = strchr(hostname, '.'))) {
2463  *dotptr = '\0';
2464  }
2465  ast_str_append(&prompt, 0, "%s", hostname);
2466  } else {
2467  ast_str_append(&prompt, 0, "%s", "localhost");
2468  }
2469  break;
2470 #ifdef HAVE_GETLOADAVG
2471  case 'l': /* load avg */
2472  t++;
2473  if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2474  double list[3];
2475  getloadavg(list, 3);
2476  ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2477  cli_prompt_changes++;
2478  }
2479  break;
2480 #endif
2481  case 's': /* Asterisk system name (from asterisk.conf) */
2482  ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
2483  break;
2484  case 't': /* time */
2485  if (ast_localtime(&ts, &tm, NULL)) {
2486  ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2487  ast_str_append(&prompt, 0, "%s", tmp);
2488  cli_prompt_changes++;
2489  }
2490  break;
2491  case 'u': /* username */
2492  if ((pw = getpwuid(getuid()))) {
2493  ast_str_append(&prompt, 0, "%s", pw->pw_name);
2494  }
2495  break;
2496  case '#': /* process console or remote? */
2497  ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2498  break;
2499  case '%': /* literal % */
2500  ast_str_append(&prompt, 0, "%c", '%');
2501  break;
2502  case '\0': /* % is last character - prevent bug */
2503  t--;
2504  break;
2505  }
2506  } else {
2507  ast_str_append(&prompt, 0, "%c", *t);
2508  }
2509  t++;
2510  }
2511  if (color_used) {
2512  /* Force colors back to normal at end */
2513  ast_str_append(&prompt, 0, "%s", term_color_code(term_code, 0, 0, sizeof(term_code)));
2514  }
2515  } else if (remotehostname) {
2517  } else {
2518  ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT);
2519  }
2520 
2521  return ast_str_buffer(prompt);
2522 }
2523 
2524 static void destroy_match_list(char **match_list, int matches)
2525 {
2526  if (match_list) {
2527  int idx;
2528 
2529  for (idx = 0; idx < matches; ++idx) {
2530  ast_free(match_list[idx]);
2531  }
2532  ast_free(match_list);
2533  }
2534 }
2535 
2536 static char **ast_el_strtoarr(char *buf)
2537 {
2538  char *retstr;
2539  char **match_list = NULL;
2540  char **new_list;
2541  size_t match_list_len = 1;
2542  int matches = 0;
2543 
2544  while ((retstr = strsep(&buf, " "))) {
2545  if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
2546  break;
2547  }
2548  if (matches + 1 >= match_list_len) {
2549  match_list_len <<= 1;
2550  new_list = ast_realloc(match_list, match_list_len * sizeof(char *));
2551  if (!new_list) {
2552  destroy_match_list(match_list, matches);
2553  return NULL;
2554  }
2555  match_list = new_list;
2556  }
2557 
2558  retstr = ast_strdup(retstr);
2559  if (!retstr) {
2560  destroy_match_list(match_list, matches);
2561  return NULL;
2562  }
2563  match_list[matches++] = retstr;
2564  }
2565 
2566  if (!match_list) {
2567  return NULL;
2568  }
2569 
2570  if (matches >= match_list_len) {
2571  new_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *));
2572  if (!new_list) {
2573  destroy_match_list(match_list, matches);
2574  return NULL;
2575  }
2576  match_list = new_list;
2577  }
2578 
2579  match_list[matches] = NULL;
2580 
2581  return match_list;
2582 }
2583 
2584 static int ast_el_sort_compare(const void *i1, const void *i2)
2585 {
2586  char *s1, *s2;
2587 
2588  s1 = ((char **)i1)[0];
2589  s2 = ((char **)i2)[0];
2590 
2591  return strcasecmp(s1, s2);
2592 }
2593 
2594 static int ast_cli_display_match_list(char **matches, int len, int max)
2595 {
2596  int i, idx, limit, count;
2597  int screenwidth = 0;
2598  int numoutput = 0, numoutputline = 0;
2599 
2600  screenwidth = ast_get_termcols(STDOUT_FILENO);
2601 
2602  /* find out how many entries can be put on one line, with two spaces between strings */
2603  limit = screenwidth / (max + 2);
2604  if (limit == 0)
2605  limit = 1;
2606 
2607  /* how many lines of output */
2608  count = len / limit;
2609  if (count * limit < len)
2610  count++;
2611 
2612  idx = 1;
2613 
2614  qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
2615 
2616  for (; count > 0; count--) {
2617  numoutputline = 0;
2618  for (i = 0; i < limit && matches[idx]; i++, idx++) {
2619 
2620  /* Don't print dupes */
2621  if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
2622  i--;
2623  ast_free(matches[idx]);
2624  matches[idx] = NULL;
2625  continue;
2626  }
2627 
2628  numoutput++;
2629  numoutputline++;
2630  fprintf(stdout, "%-*s ", max, matches[idx]);
2631  ast_free(matches[idx]);
2632  matches[idx] = NULL;
2633  }
2634  if (numoutputline > 0)
2635  fprintf(stdout, "\n");
2636  }
2637 
2638  return numoutput;
2639 }
2640 
2641 
2642 static char *cli_complete(EditLine *editline, int ch)
2643 {
2644  int len = 0;
2645  char *ptr;
2646  int nummatches = 0;
2647  char **matches;
2648  int retval = CC_ERROR;
2649  char buf[2048], savechr;
2650  int res;
2651 
2652  LineInfo *lf = (LineInfo *)el_line(editline);
2653 
2654  savechr = *(char *)lf->cursor;
2655  *(char *)lf->cursor = '\0';
2656  ptr = (char *)lf->cursor;
2657  if (ptr) {
2658  while (ptr > lf->buffer) {
2659  if (isspace(*ptr)) {
2660  ptr++;
2661  break;
2662  }
2663  ptr--;
2664  }
2665  }
2666 
2667  len = lf->cursor - ptr;
2668 
2669  if (ast_opt_remote) {
2670  snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
2671  fdsend(ast_consock, buf);
2672  if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {
2673  return (char*)(CC_ERROR);
2674  }
2675  buf[res] = '\0';
2676  nummatches = atoi(buf);
2677 
2678  if (nummatches > 0) {
2679  char *mbuf;
2680  char *new_mbuf;
2681  int mlen = 0, maxmbuf = 2048;
2682 
2683  /* Start with a 2048 byte buffer */
2684  if (!(mbuf = ast_malloc(maxmbuf))) {
2685  lf->cursor[0] = savechr;
2686  return (char *)(CC_ERROR);
2687  }
2688  snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
2689  fdsend(ast_consock, buf);
2690  res = 0;
2691  mbuf[0] = '\0';
2692  while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
2693  if (mlen + 1024 > maxmbuf) {
2694  /* Every step increment buffer 1024 bytes */
2695  maxmbuf += 1024;
2696  new_mbuf = ast_realloc(mbuf, maxmbuf);
2697  if (!new_mbuf) {
2698  ast_free(mbuf);
2699  lf->cursor[0] = savechr;
2700  return (char *)(CC_ERROR);
2701  }
2702  mbuf = new_mbuf;
2703  }
2704  /* Only read 1024 bytes at a time */
2705  res = read(ast_consock, mbuf + mlen, 1024);
2706  if (res > 0)
2707  mlen += res;
2708  }
2709  mbuf[mlen] = '\0';
2710 
2711  matches = ast_el_strtoarr(mbuf);
2712  ast_free(mbuf);
2713  } else
2714  matches = (char **) NULL;
2715  } else {
2716  char **p, *oldbuf=NULL;
2717  nummatches = 0;
2718  matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
2719  for (p = matches; p && *p; p++) {
2720  if (!oldbuf || strcmp(*p,oldbuf))
2721  nummatches++;
2722  oldbuf = *p;
2723  }
2724  }
2725 
2726  if (matches) {
2727  int i;
2728  int matches_num, maxlen, match_len;
2729 
2730  if (matches[0][0] != '\0') {
2731  el_deletestr(editline, (int) len);
2732  el_insertstr(editline, matches[0]);
2733  retval = CC_REFRESH;
2734  }
2735 
2736  if (nummatches == 1) {
2737  /* Found an exact match */
2738  el_insertstr(editline, " ");
2739  retval = CC_REFRESH;
2740  } else {
2741  /* Must be more than one match */
2742  for (i = 1, maxlen = 0; matches[i]; i++) {
2743  match_len = strlen(matches[i]);
2744  if (match_len > maxlen)
2745  maxlen = match_len;
2746  }
2747  matches_num = i - 1;
2748  if (matches_num >1) {
2749  fprintf(stdout, "\n");
2750  ast_cli_display_match_list(matches, nummatches, maxlen);
2751  retval = CC_REDISPLAY;
2752  } else {
2753  el_insertstr(editline," ");
2754  retval = CC_REFRESH;
2755  }
2756  }
2757  for (i = 0; matches[i]; i++)
2758  ast_free(matches[i]);
2759  ast_free(matches);
2760  }
2761 
2762  lf->cursor[0] = savechr;
2763 
2764  return (char *)(long)retval;
2765 }
2766 
2767 static int ast_el_initialize(void)
2768 {
2769  HistEvent ev;
2770  char *editor = getenv("AST_EDITOR");
2771 
2772  if (el != NULL)
2773  el_end(el);
2774  if (el_hist != NULL)
2775  history_end(el_hist);
2776 
2777  el = el_init("asterisk", stdin, stdout, stderr);
2778  el_set(el, EL_PROMPT, cli_prompt);
2779 
2780  el_set(el, EL_EDITMODE, 1);
2781  el_set(el, EL_EDITOR, editor ? editor : "emacs");
2782  el_hist = history_init();
2783  if (!el || !el_hist)
2784  return -1;
2785 
2786  /* setup history with 100 entries */
2787  history(el_hist, &ev, H_SETSIZE, 100);
2788 
2789  el_set(el, EL_HIST, history, el_hist);
2790 
2791  el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
2792  /* Bind <tab> to command completion */
2793  el_set(el, EL_BIND, "^I", "ed-complete", NULL);
2794  /* Bind ? to command completion */
2795  el_set(el, EL_BIND, "?", "ed-complete", NULL);
2796  /* Bind ^D to redisplay */
2797  el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
2798 
2799  return 0;
2800 }
2801 
2802 #define MAX_HISTORY_COMMAND_LENGTH 256
2803 
2804 static int ast_el_add_history(char *buf)
2805 {
2806  HistEvent ev;
2807 
2808  if (el_hist == NULL || el == NULL)
2810  if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1))
2811  return 0;
2812  return (history(el_hist, &ev, H_ENTER, ast_strip(ast_strdupa(buf))));
2813 }
2814 
2815 static int ast_el_write_history(char *filename)
2816 {
2817  HistEvent ev;
2818 
2819  if (el_hist == NULL || el == NULL)
2821 
2822  return (history(el_hist, &ev, H_SAVE, filename));
2823 }
2824 
2825 static int ast_el_read_history(char *filename)
2826 {
2827  char buf[MAX_HISTORY_COMMAND_LENGTH];
2828  FILE *f;
2829  int ret = -1;
2830 
2831  if (el_hist == NULL || el == NULL)
2833 
2834  if ((f = fopen(filename, "r")) == NULL)
2835  return ret;
2836 
2837  while (!feof(f)) {
2838  if (!fgets(buf, sizeof(buf), f))
2839  break;
2840  if (!strcmp(buf, "_HiStOrY_V2_\n"))
2841  continue;
2842  if (ast_all_zeros(buf))
2843  continue;
2844  if ((ret = ast_el_add_history(buf)) == -1)
2845  break;
2846  }
2847  fclose(f);
2848 
2849  return ret;
2850 }
2851 
2852 static void ast_remotecontrol(char *data)
2853 {
2854  char buf[80];
2855  int res;
2856  char filename[80] = "";
2857  char *hostname;
2858  char *cpid;
2859  char *version;
2860  int pid;
2861  char *stringp = NULL;
2862 
2863  char *ebuf;
2864  int num = 0;
2865 
2866  memset(&sig_flags, 0, sizeof(sig_flags));
2867  signal(SIGINT, __remote_quit_handler);
2868  signal(SIGTERM, __remote_quit_handler);
2869  signal(SIGHUP, __remote_quit_handler);
2870 
2871  if (read(ast_consock, buf, sizeof(buf)) < 0) {
2872  ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
2873  return;
2874  }
2875  if (data) {
2876  char prefix[] = "cli quit after ";
2877  char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
2878  sprintf(tmp, "%s%s", prefix, data);
2879  if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
2880  ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
2881  if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2882  return;
2883  }
2884  }
2885  }
2886  stringp = buf;
2887  hostname = strsep(&stringp, "/");
2888  cpid = strsep(&stringp, "/");
2889  version = strsep(&stringp, "\n");
2890  if (!version)
2891  version = "<Version Unknown>";
2892  stringp = hostname;
2893  strsep(&stringp, ".");
2894  if (cpid)
2895  pid = atoi(cpid);
2896  else
2897  pid = -1;
2898  if (!data) {
2899  char tmp[80];
2900  snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
2901  fdsend(ast_consock, tmp);
2902  snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
2903  fdsend(ast_consock, tmp);
2904  if (!ast_opt_mute)
2905  fdsend(ast_consock, "logger mute silent");
2906  else
2907  printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2908  }
2909 
2910  if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
2911  struct pollfd fds;
2912  fds.fd = ast_consock;
2913  fds.events = POLLIN;
2914  fds.revents = 0;
2915  while (ast_poll(&fds, 1, 60000) > 0) {
2916  char buffer[512] = "", *curline = buffer, *nextline;
2917  int not_written = 1;
2918 
2919  if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2920  break;
2921  }
2922 
2923  if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
2924  break;
2925  }
2926 
2927  do {
2928  if ((nextline = strchr(curline, '\n'))) {
2929  nextline++;
2930  } else {
2931  nextline = strchr(curline, '\0');
2932  }
2933 
2934  /* Skip verbose lines */
2935  if (*curline != 127) {
2936  not_written = 0;
2937  if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
2938  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
2939  }
2940  }
2941  curline = nextline;
2942  } while (!ast_strlen_zero(curline));
2943 
2944  /* No non-verbose output in 60 seconds. */
2945  if (not_written) {
2946  break;
2947  }
2948  }
2949  return;
2950  }
2951 
2952  ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
2954  if (getenv("HOME"))
2955  snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
2956  if (el_hist == NULL || el == NULL)
2958 
2959  el_set(el, EL_GETCFN, ast_el_read_char);
2960 
2961  if (!ast_strlen_zero(filename))
2962  ast_el_read_history(filename);
2963 
2964  for (;;) {
2965  ebuf = (char *)el_gets(el, &num);
2966 
2967  if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2968  break;
2969  }
2970 
2971  if (!ebuf && write(1, "", 1) < 0)
2972  break;
2973 
2974  if (!ast_strlen_zero(ebuf)) {
2975  if (ebuf[strlen(ebuf)-1] == '\n')
2976  ebuf[strlen(ebuf)-1] = '\0';
2977  if (!remoteconsolehandler(ebuf)) {
2978  /* Strip preamble from output */
2979  char *temp;
2980  for (temp = ebuf; *temp; temp++) {
2981  if (*temp == 127) {
2982  memmove(temp, temp + 1, strlen(temp));
2983  temp--;
2984  }
2985  }
2986  res = write(ast_consock, ebuf, strlen(ebuf) + 1);
2987  if (res < 1) {
2988  ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
2989  break;
2990  }
2991  }
2992  }
2993  }
2994  printf("\nDisconnected from Asterisk server\n");
2995 }
2996 
2997 static int show_version(void)
2998 {
2999  printf("Asterisk %s\n", ast_get_version());
3000  return 0;
3001 }
3002 
3003 static int show_cli_help(void)
3004 {
3005  printf("Asterisk %s, Copyright (C) 1999 - 2013, Digium, Inc. and others.\n", ast_get_version());
3006  printf("Usage: asterisk [OPTIONS]\n");
3007  printf("Valid Options:\n");
3008  printf(" -V Display version number and exit\n");
3009  printf(" -C <configfile> Use an alternate configuration file\n");
3010  printf(" -G <group> Run as a group other than the caller\n");
3011  printf(" -U <user> Run as a user other than the caller\n");
3012  printf(" -c Provide console CLI\n");
3013  printf(" -d Enable extra debugging\n");
3014 #if HAVE_WORKING_FORK
3015  printf(" -f Do not fork\n");
3016  printf(" -F Always fork\n");
3017 #endif
3018  printf(" -g Dump core in case of a crash\n");
3019  printf(" -h This help screen\n");
3020  printf(" -i Initialize crypto keys at startup\n");
3021  printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
3022  printf(" -M <value> Limit the maximum number of calls to the specified value\n");
3023  printf(" -m Mute debugging and console output on the console\n");
3024  printf(" -n Disable console colorization\n");
3025  printf(" -p Run as pseudo-realtime thread\n");
3026  printf(" -q Quiet mode (suppress output)\n");
3027  printf(" -r Connect to Asterisk on this machine\n");
3028  printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
3029  printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
3030  printf(" -t Record soundfiles in /var/tmp and move them where they\n");
3031  printf(" belong after they are done\n");
3032  printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3033  printf(" of output to the CLI\n");
3034  printf(" -v Increase verbosity (multiple v's = more verbose)\n");
3035  printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
3036  printf(" -X Execute includes by default (allows #exec in asterisk.conf)\n");
3037  printf(" -W Adjust terminal colors to compensate for a light background\n");
3038  printf("\n");
3039  return 0;
3040 }
3041 
3042 static void ast_readconfig(void)
3043 {
3044  struct ast_config *cfg;
3045  struct ast_variable *v;
3046  char *config = DEFAULT_CONFIG_FILE;
3047  char hostname[MAXHOSTNAMELEN] = "";
3048  struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
3049  struct {
3050  unsigned int dbdir:1;
3051  unsigned int keydir:1;
3052  } found = { 0, 0 };
3053  /* Default to true for backward compatibility */
3054  int live_dangerously = 1;
3055 
3057  cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
3059  fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
3060  }
3061  } else {
3062  cfg = ast_config_load2(config, "" /* core, can't reload */, config_flags);
3063  }
3064 
3065  /* init with buildtime config */
3069  snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
3079 
3081 
3082  /* no asterisk.conf? no problem, use buildtime config! */
3084  return;
3085  }
3086 
3087  for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
3088  if (!strcasecmp(v->name, "astctlpermissions"))
3090  else if (!strcasecmp(v->name, "astctlowner"))
3092  else if (!strcasecmp(v->name, "astctlgroup"))
3094  else if (!strcasecmp(v->name, "astctl"))
3096  }
3097 
3098  for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
3099  if (!strcasecmp(v->name, "astetcdir")) {
3101  } else if (!strcasecmp(v->name, "astspooldir")) {
3103  snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
3104  } else if (!strcasecmp(v->name, "astvarlibdir")) {
3106  if (!found.dbdir)
3107  snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3108  } else if (!strcasecmp(v->name, "astdbdir")) {
3109  snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3110  found.dbdir = 1;
3111  } else if (!strcasecmp(v->name, "astdatadir")) {
3113  if (!found.keydir)
3114  snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3115  } else if (!strcasecmp(v->name, "astkeydir")) {
3116  snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3117  found.keydir = 1;
3118  } else if (!strcasecmp(v->name, "astlogdir")) {
3120  } else if (!strcasecmp(v->name, "astagidir")) {
3122  } else if (!strcasecmp(v->name, "astrundir")) {
3123  snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
3124  snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
3126  } else if (!strcasecmp(v->name, "astmoddir")) {
3128  }
3129  }
3130 
3131  for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
3132  /* verbose level (-v at startup) */
3133  if (!strcasecmp(v->name, "verbose")) {
3134  option_verbose = atoi(v->value);
3135  /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
3136  } else if (!strcasecmp(v->name, "timestamp")) {
3137  ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
3138  /* whether or not to support #exec in config files */
3139  } else if (!strcasecmp(v->name, "execincludes")) {
3141  /* debug level (-d at startup) */
3142  } else if (!strcasecmp(v->name, "debug")) {
3143  option_debug = 0;
3144  if (sscanf(v->value, "%30d", &option_debug) != 1) {
3145  option_debug = ast_true(v->value);
3146  }
3147 #if HAVE_WORKING_FORK
3148  /* Disable forking (-f at startup) */
3149  } else if (!strcasecmp(v->name, "nofork")) {
3150  ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
3151  /* Always fork, even if verbose or debug are enabled (-F at startup) */
3152  } else if (!strcasecmp(v->name, "alwaysfork")) {
3154 #endif
3155  /* Run quietly (-q at startup ) */
3156  } else if (!strcasecmp(v->name, "quiet")) {
3157  ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
3158  /* Run as console (-c at startup, implies nofork) */
3159  } else if (!strcasecmp(v->name, "console")) {
3161  /* Run with high priority if the O/S permits (-p at startup) */
3162  } else if (!strcasecmp(v->name, "highpriority")) {
3164  /* Initialize RSA auth keys (IAX2) (-i at startup) */
3165  } else if (!strcasecmp(v->name, "initcrypto")) {
3166  ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
3167  /* Disable ANSI colors for console (-c at startup) */
3168  } else if (!strcasecmp(v->name, "nocolor")) {
3169  ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
3170  /* Disable some usage warnings for picky people :p */
3171  } else if (!strcasecmp(v->name, "dontwarn")) {
3172  ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
3173  /* Dump core in case of crash (-g) */
3174  } else if (!strcasecmp(v->name, "dumpcore")) {
3175  ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
3176  /* Cache recorded sound files to another directory during recording */
3177  } else if (!strcasecmp(v->name, "cache_record_files")) {
3179  /* Specify cache directory */
3180  } else if (!strcasecmp(v->name, "record_cache_dir")) {
3181  ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
3182  /* Build transcode paths via SLINEAR, instead of directly */
3183  } else if (!strcasecmp(v->name, "transcode_via_sln")) {
3185  /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
3186  } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
3188  /* Enable internal timing */
3189  } else if (!strcasecmp(v->name, "internal_timing")) {
3190  if (!ast_opt_remote) {
3191  fprintf(stderr,
3192  "NOTICE: The internal_timing option is no longer needed.\n"
3193  " It will always be enabled if you have a timing module loaded.\n");
3194  }
3195  } else if (!strcasecmp(v->name, "maxcalls")) {
3196  if ((sscanf(v->value, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
3197  option_maxcalls = 0;
3198  }
3199  } else if (!strcasecmp(v->name, "maxload")) {
3200  double test[1];
3201 
3202  if (getloadavg(test, 1) == -1) {
3203  ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
3204  option_maxload = 0.0;
3205  } else if ((sscanf(v->value, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
3206  option_maxload = 0.0;
3207  }
3208  /* Set the maximum amount of open files */
3209  } else if (!strcasecmp(v->name, "maxfiles")) {
3210  option_maxfiles = atoi(v->value);
3211  set_ulimit(option_maxfiles);
3212  /* What user to run as */
3213  } else if (!strcasecmp(v->name, "runuser")) {
3215  /* What group to run as */
3216  } else if (!strcasecmp(v->name, "rungroup")) {
3218  } else if (!strcasecmp(v->name, "systemname")) {
3220  } else if (!strcasecmp(v->name, "autosystemname")) {
3221  if (ast_true(v->value)) {
3222  if (!gethostname(hostname, sizeof(hostname) - 1))
3224  else {
3227  }
3228  ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
3229  }
3230  }
3231  } else if (!strcasecmp(v->name, "languageprefix")) {
3233  } else if (!strcasecmp(v->name, "defaultlanguage")) {
3235  } else if (!strcasecmp(v->name, "lockmode")) {
3236  if (!strcasecmp(v->value, "lockfile")) {
3238  } else if (!strcasecmp(v->value, "flock")) {
3240  } else {
3241  ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
3242  "defaulting to 'lockfile'\n", v->value);
3244  }
3245 #if defined(HAVE_SYSINFO)
3246  } else if (!strcasecmp(v->name, "minmemfree")) {
3247  /* specify the minimum amount of free memory to retain. Asterisk should stop accepting new calls
3248  * if the amount of free memory falls below this watermark */
3249  if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3250  option_minmemfree = 0;
3251  }
3252 #endif
3253  } else if (!strcasecmp(v->name, "entityid")) {
3254  struct ast_eid tmp_eid;
3255  if (!ast_str_to_eid(&tmp_eid, v->value)) {
3256  ast_verbose("Successfully set global EID to '%s'\n", v->value);
3257  ast_eid_default = tmp_eid;
3258  } else
3259  ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
3260  } else if (!strcasecmp(v->name, "lightbackground")) {
3262  } else if (!strcasecmp(v->name, "forceblackbackground")) {
3264  } else if (!strcasecmp(v->name, "hideconnect")) {
3266  } else if (!strcasecmp(v->name, "lockconfdir")) {
3268  } else if (!strcasecmp(v->name, "live_dangerously")) {
3269  live_dangerously = ast_true(v->value);
3270  }
3271  }
3272  if (!ast_opt_remote) {
3273  pbx_live_dangerously(live_dangerously);
3274  }
3275  for (v = ast_variable_browse(cfg, "compat"); v; v = v->next) {
3276  float version;
3277  if (sscanf(v->value, "%30f", &version) != 1) {
3278  fprintf(stderr, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
3279  continue;
3280  }
3281  if (!strcasecmp(v->name, "app_set")) {
3282  ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_APP_SET);
3283  } else if (!strcasecmp(v->name, "res_agi")) {
3284  ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_RES_AGI);
3285  } else if (!strcasecmp(v->name, "pbx_realtime")) {
3286  ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_PBX_REALTIME);
3287  }
3288  }
3289  ast_config_destroy(cfg);
3290 }
3291 
3292 static void *monitor_sig_flags(void *unused)
3293 {
3294  for (;;) {
3295  struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
3296  int a;
3297  ast_poll(&p, 1, -1);
3298  if (sig_flags.need_reload) {
3299  sig_flags.need_reload = 0;
3300  ast_module_reload(NULL);
3301  }
3302  if (sig_flags.need_quit) {
3303  sig_flags.need_quit = 0;
3304  if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
3305  sig_flags.need_quit_handler = 1;
3306  pthread_kill(consolethread, SIGURG);
3307  } else {
3309  }
3310  }
3311  if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
3312  }
3313  }
3314 
3315  return NULL;
3316 }
3317 
3318 static void *canary_thread(void *unused)
3319 {
3320  struct stat canary_stat;
3321  struct timeval now;
3322 
3323  /* Give the canary time to sing */
3324  sleep(120);
3325 
3326  for (;;) {
3327  now = ast_tvnow();
3328  if (stat(canary_filename, &canary_stat) || now.tv_sec > canary_stat.st_mtime + 60) {
3330  "The canary is no more. He has ceased to be! "
3331  "He's expired and gone to meet his maker! "
3332  "He's a stiff! Bereft of life, he rests in peace. "
3333  "His metabolic processes are now history! He's off the twig! "
3334  "He's kicked the bucket. He's shuffled off his mortal coil, "
3335  "run down the curtain, and joined the bleeding choir invisible!! "
3336  "THIS is an EX-CANARY. (Reducing priority)\n");
3337  ast_set_priority(0);
3338  pthread_exit(NULL);
3339  }
3340 
3341  /* Check the canary once a minute */
3342  sleep(60);
3343  }
3344 }
3345 
3346 /* Used by libc's atexit(3) function */
3347 static void canary_exit(void)
3348 {
3349  if (canary_pid > 0)
3350  kill(canary_pid, SIGKILL);
3351 }
3352 
3353 static void run_startup_commands(void)
3354 {
3355  int fd;
3356  struct ast_config *cfg;
3357  struct ast_flags cfg_flags = { 0 };
3358  struct ast_variable *v;
3359 
3360  if (!(cfg = ast_config_load2("cli.conf", "" /* core, can't reload */, cfg_flags)))
3361  return;
3363  return;
3364  }
3365 
3366  fd = open("/dev/null", O_RDWR);
3367  if (fd < 0) {
3368  ast_config_destroy(cfg);
3369  return;
3370  }
3371 
3372  for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
3373  if (ast_true(v->value))
3374  ast_cli_command(fd, v->name);
3375  }
3376 
3377  close(fd);
3378  ast_config_destroy(cfg);
3379 }
3380 
3381 static void env_init(void)
3382 {
3383  setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
3384  setenv("AST_BUILD_HOST", ast_build_hostname, 1);
3385  setenv("AST_BUILD_DATE", ast_build_date, 1);
3386  setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
3387  setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
3388  setenv("AST_BUILD_OS", ast_build_os, 1);
3389  setenv("AST_BUILD_USER", ast_build_user, 1);
3390  setenv("AST_VERSION", ast_get_version(), 1);
3391 }
3392 
3393 static void print_intro_message(const char *runuser, const char *rungroup)
3394 {
3395  if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
3397  fprintf(stderr, "Unable to register console verboser?\n");
3398  return;
3399  }
3401  if (runuser) {
3402  ast_verbose("Running as user '%s'\n", runuser);
3403  }
3404  if (rungroup) {
3405  ast_verbose("Running under group '%s'\n", rungroup);
3406  }
3407  }
3408 }
3409 
3410 static void main_atexit(void)
3411 {
3412  ast_cli_unregister_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
3413 }
3414 
3415 int main(int argc, char *argv[])
3416 {
3417  int c;
3418  char filename[80] = "";
3419  char hostname[MAXHOSTNAMELEN] = "";
3420  char tmp[80];
3421  char * xarg = NULL;
3422  int x;
3423  FILE *f;
3424  sigset_t sigs;
3425  int num;
3426  int isroot = 1, rundir_exists = 0;
3427  char *buf;
3428  const char *runuser = NULL, *rungroup = NULL;
3429  char *remotesock = NULL;
3430  int moduleresult; /*!< Result from the module load subsystem */
3431  struct rlimit l;
3432 
3433  /* Remember original args for restart */
3434  if (argc > ARRAY_LEN(_argv) - 1) {
3435  fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
3436  argc = ARRAY_LEN(_argv) - 1;
3437  }
3438  for (x = 0; x < argc; x++)
3439  _argv[x] = argv[x];
3440  _argv[x] = NULL;
3441 
3442  if (geteuid() != 0)
3443  isroot = 0;
3444 
3445  /* if the progname is rasterisk consider it a remote console */
3446  if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
3448  }
3449  if (gethostname(hostname, sizeof(hostname)-1))
3450  ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
3451  ast_mainpid = getpid();
3452 
3453  if (getenv("HOME"))
3454  snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
3455  /* Check for options */
3456  while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) {
3457  /*!\note Please keep the ordering here to alphabetical, capital letters
3458  * first. This will make it easier in the future to select unused
3459  * option flags for new features. */
3460  switch (c) {
3461  case 'B': /* Force black background */
3464  break;
3465  case 'X':
3467  break;
3468  case 'C':
3471  break;
3472  case 'c':
3474  break;
3475  case 'd':
3476  option_debug++;
3477  ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3478  break;
3479 #if defined(HAVE_SYSINFO)
3480  case 'e':
3481  if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3482  option_minmemfree = 0;
3483  }
3484  break;
3485 #endif
3486 #if HAVE_WORKING_FORK
3487  case 'F':
3488  ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
3489  break;
3490  case 'f':
3491  ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3492  break;
3493 #endif
3494  case 'G':
3495  rungroup = ast_strdupa(optarg);
3496  break;
3497  case 'g':
3498  ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
3499  break;
3500  case 'h':
3501  show_cli_help();
3502  exit(0);
3503  case 'I':
3504  fprintf(stderr,
3505  "NOTICE: The -I option is no longer needed.\n"
3506  " It will always be enabled if you have a timing module loaded.\n");
3507  break;
3508  case 'i':
3509  ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
3510  break;
3511  case 'L':
3512  if ((sscanf(optarg, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
3513  option_maxload = 0.0;
3514  }
3515  break;
3516  case 'M':
3517  if ((sscanf(optarg, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
3518  option_maxcalls = 0;
3519  }
3520  break;
3521  case 'm':
3522  ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
3523  break;
3524  case 'n':
3525  ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
3526  break;
3527  case 'p':
3529  break;
3530  case 'q':
3531  ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
3532  break;
3533  case 'R':
3535  break;
3536  case 'r':
3538  break;
3539  case 's':
3540  remotesock = ast_strdupa(optarg);
3541  break;
3542  case 'T':
3543  ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
3544  break;
3545  case 't':
3547  break;
3548  case 'U':
3549  runuser = ast_strdupa(optarg);
3550  break;
3551  case 'V':
3552  show_version();
3553  exit(0);
3554  case 'v':
3555  option_verbose++;
3556  ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3557  break;
3558  case 'W': /* White background */
3561  break;
3562  case 'x':
3563  /* -r is implied by -x so set the flags -r sets as well. */
3565 
3567  xarg = ast_strdupa(optarg);
3568  break;
3569  case '?':
3570  exit(1);
3571  }
3572  }
3573 
3574  /* For remote connections, change the name of the remote connection.
3575  * We do this for the benefit of init scripts (which need to know if/when
3576  * the main asterisk process has died yet). */
3577  if (ast_opt_remote) {
3578  strcpy(argv[0], "rasterisk");
3579  for (x = 1; x < argc; x++) {
3580  argv[x] = argv[0] + 10;
3581  }
3582  }
3583 
3584  ast_readconfig();
3585  env_init();
3586 
3587  if (ast_opt_remote && remotesock != NULL)
3588  ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
3589 
3591  fprintf(stderr, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n");
3592  }
3593 
3595  fprintf(stderr, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
3597  }
3598 
3599  if (ast_opt_dump_core) {
3600  memset(&l, 0, sizeof(l));
3601  l.rlim_cur = RLIM_INFINITY;
3602  l.rlim_max = RLIM_INFINITY;
3603  if (setrlimit(RLIMIT_CORE, &l)) {
3604  fprintf(stderr, "Unable to disable core size resource limit: %s\n", strerror(errno));
3605  }
3606  }
3607 
3608  if (getrlimit(RLIMIT_NOFILE, &l)) {
3609  fprintf(stderr, "Unable to check file descriptor limit: %s\n", strerror(errno));
3610  }
3611 
3612 #if !defined(CONFIGURE_RAN_AS_ROOT)
3613  /* Check if select(2) will run with more file descriptors */
3614  do {
3615  int fd, fd2;
3616  ast_fdset readers;
3617  struct timeval tv = { 0, };
3618 
3619  if (l.rlim_cur <= FD_SETSIZE) {
3620  /* The limit of select()able FDs is irrelevant, because we'll never
3621  * open one that high. */
3622  break;
3623  }
3624 
3625  if (!(fd = open("/dev/null", O_RDONLY))) {
3626  fprintf(stderr, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
3627  break; /* XXX Should we exit() here? XXX */
3628  }
3629 
3630  fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
3631  if (dup2(fd, fd2) < 0) {
3632  fprintf(stderr, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
3633  close(fd);
3634  break;
3635  }
3636 
3637  FD_ZERO(&readers);
3638  FD_SET(fd2, &readers);
3639  if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
3640  fprintf(stderr, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
3641  }
3642  ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3643  close(fd);
3644  close(fd2);
3645  } while (0);
3646 #elif defined(HAVE_VARIABLE_FDSET)
3647  ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3648 #endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
3649 
3650  if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
3651  rungroup = ast_config_AST_RUN_GROUP;
3652  if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
3653  runuser = ast_config_AST_RUN_USER;
3654 
3655  /* Must install this signal handler up here to ensure that if the canary
3656  * fails to execute that it doesn't kill the Asterisk process.
3657  */
3658  sigaction(SIGCHLD, &child_handler, NULL);
3659 
3660  /* It's common on some platforms to clear /var/run at boot. Create the
3661  * socket file directory before we drop privileges. */
3662  if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
3663  if (errno == EEXIST) {
3664  rundir_exists = 1;
3665  } else {
3666  fprintf(stderr, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
3667  }
3668  }
3669 
3670 #ifndef __CYGWIN__
3671 
3672  if (isroot) {
3674  }
3675 
3676  if (isroot && rungroup) {
3677  struct group *gr;
3678  gr = getgrnam(rungroup);
3679  if (!gr) {
3680  fprintf(stderr, "No such group '%s'!\n", rungroup);
3681  exit(1);
3682  }
3683  if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
3684  fprintf(stderr, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
3685  }
3686  if (setgid(gr->gr_gid)) {
3687  fprintf(stderr, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
3688  exit(1);
3689  }
3690  if (setgroups(0, NULL)) {
3691  fprintf(stderr, "Unable to drop unneeded groups\n");
3692  exit(1);
3693  }
3694  }
3695 
3696  if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
3697 #ifdef HAVE_CAP
3698  int has_cap = 1;
3699 #endif /* HAVE_CAP */
3700  struct passwd *pw;
3701  pw = getpwnam(runuser);
3702  if (!pw) {
3703  fprintf(stderr, "No such user '%s'!\n", runuser);
3704  exit(1);
3705  }
3706  if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
3707  fprintf(stderr, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
3708  }
3709 #ifdef HAVE_CAP
3710  if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
3711  ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
3712  has_cap = 0;
3713  }
3714 #endif /* HAVE_CAP */
3715  if (!isroot && pw->pw_uid != geteuid()) {
3716  fprintf(stderr, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
3717  exit(1);
3718  }
3719  if (!rungroup) {
3720  if (setgid(pw->pw_gid)) {
3721  fprintf(stderr, "Unable to setgid to %d!\n", (int)pw->pw_gid);
3722  exit(1);
3723  }
3724  if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
3725  fprintf(stderr, "Unable to init groups for '%s'\n", runuser);
3726  exit(1);
3727  }
3728  }
3729  if (setuid(pw->pw_uid)) {
3730  fprintf(stderr, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
3731  exit(1);
3732  }
3733 #ifdef HAVE_CAP
3734  if (has_cap) {
3735  cap_t cap;
3736 
3737  cap = cap_from_text("cap_net_admin=eip");
3738 
3739  if (cap_set_proc(cap)) {
3740  fprintf(stderr, "Unable to install capabilities.\n");
3741  }
3742  if (cap_free(cap)) {
3743  fprintf(stderr, "Unable to drop capabilities.\n");
3744  }
3745  }
3746 #endif /* HAVE_CAP */
3747  }
3748 
3749 #endif /* __CYGWIN__ */
3750 
3751 #ifdef linux
3752  if (geteuid() && ast_opt_dump_core) {
3753  if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
3754  fprintf(stderr, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
3755  }
3756  }
3757 #endif
3758 
3759  {
3760 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
3761 #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
3762 #define eaccess euidaccess
3763 #endif
3764  char dir[PATH_MAX];
3765  if (!getcwd(dir, sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
3766  fprintf(stderr, "Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
3767  /* If we cannot access the CWD, then we couldn't dump core anyway,
3768  * so chdir("/") won't break anything. */
3769  if (chdir("/")) {
3770  /* chdir(/) should never fail, so this ends up being a no-op */
3771  fprintf(stderr, "chdir(\"/\") failed?!! %s\n", strerror(errno));
3772  }
3773  } else
3774 #endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
3776  /* Backgrounding, but no cores, so chdir won't break anything. */
3777  if (chdir("/")) {
3778  fprintf(stderr, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
3779  }
3780  }
3781  }
3782 
3783  if (ast_tryconnect()) {
3784  /* One is already running */
3785  if (ast_opt_remote) {
3786  multi_thread_safe = 1;
3787  if (ast_opt_exec) {
3788  ast_remotecontrol(xarg);
3789  quit_handler(0, SHUTDOWN_FAST, 0);
3790  exit(0);
3791  }
3792  print_intro_message(runuser, rungroup);
3793  printf("%s", term_quit());
3794  ast_remotecontrol(NULL);
3795  quit_handler(0, SHUTDOWN_FAST, 0);
3796  exit(0);
3797  } else {
3798  fprintf(stderr, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
3799  printf("%s", term_quit());
3800  exit(1);
3801  }
3802  } else if (ast_opt_remote || ast_opt_exec) {
3803  fprintf(stderr, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
3804  printf("%s", term_quit());
3805  exit(1);
3806  }
3807 
3808  /* This needs to remain as high up in the initial start up as possible.
3809  * daemon causes a fork to occur, which has all sorts of unintended
3810  * consequences for things that interact with threads. This call *must*
3811  * occur before anything in Asterisk spawns or manipulates thread related
3812  * primitives. */
3813 #if HAVE_WORKING_FORK
3815 #ifndef HAVE_SBIN_LAUNCHD
3816  if (daemon(1, 0) < 0) {
3817  fprintf(stderr, "daemon() failed: %s\n", strerror(errno));
3818  } else {
3819  ast_mainpid = getpid();
3820  }
3821 #else
3822  fprintf(stderr, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
3823 #endif
3824  }
3825 #endif
3826 
3827  /* At this point everything has been forked successfully,
3828  * we have determined that we aren't attempting to connect to
3829  * an Asterisk instance, and that there isn't one already running. */
3830  multi_thread_safe = 1;
3831 
3832 #if defined(__AST_DEBUG_MALLOC)
3834 #endif /* defined(__AST_DEBUG_MALLOC) */
3835 
3836  /* Spawning of astcanary must happen AFTER the call to daemon(3) */
3837  if (isroot && ast_opt_high_priority) {
3838  snprintf(canary_filename, sizeof(canary_filename), "%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
3839 
3840  /* Don't let the canary child kill Asterisk, if it dies immediately */
3841  sigaction(SIGPIPE, &ignore_sig_handler, NULL);
3842 
3843  canary_pid = fork();
3844  if (canary_pid == 0) {
3845  char canary_binary[128], *lastslash, ppid[12];
3846 
3847  /* Reset signal handler */
3848  signal(SIGCHLD, SIG_DFL);
3849  signal(SIGPIPE, SIG_DFL);
3850 
3852  ast_set_priority(0);
3853  snprintf(ppid, sizeof(ppid), "%d", (int) ast_mainpid);
3854 
3855  execlp("astcanary", "astcanary", canary_filename, ppid, (char *)NULL);
3856 
3857  /* If not found, try the same path as used to execute asterisk */
3858  ast_copy_string(canary_binary, argv[0], sizeof(canary_binary));
3859  if ((lastslash = strrchr(canary_binary, '/'))) {
3860  ast_copy_string(lastslash + 1, "astcanary", sizeof(canary_binary) + canary_binary - (lastslash + 1));
3861  execl(canary_binary, "astcanary", canary_filename, ppid, (char *)NULL);
3862  }
3863 
3864  /* Should never happen */
3865  _exit(1);
3866  } else if (canary_pid > 0) {
3867  pthread_t dont_care;
3868  ast_pthread_create_detached(&dont_care, NULL, canary_thread, NULL);
3869  }
3870 
3871  /* Kill the canary when we exit */
3873  }
3874 
3875  /* Blindly write the PID file. */
3876  unlink(ast_config_AST_PID);
3877  f = fopen(ast_config_AST_PID, "w");
3878  if (f) {
3879  fprintf(f, "%ld\n", (long)ast_mainpid);
3880  fclose(f);
3881  } else {
3882  fprintf(stderr, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
3883  }
3884 
3885  /* Initialize the terminal. Since all processes have been forked,
3886  * we can now start using the standard log messages.
3887  */
3888  ast_term_init();
3889  printf("%s", term_end());
3890  fflush(stdout);
3891 
3892  print_intro_message(runuser, rungroup);
3893 
3894  if (ast_opt_console && !option_verbose) {
3895  ast_verbose("[ Initializing Custom Configuration Options ]\n");
3896  }
3897  /* custom config setup */
3899  read_config_maps();
3900 
3901  astobj2_init();
3902 
3903  if (ast_opt_console) {
3904  if (el_hist == NULL || el == NULL)
3906 
3907  if (!ast_strlen_zero(filename))
3908  ast_el_read_history(filename);
3909  }
3910 
3911  ast_ulaw_init();
3912  ast_alaw_init();
3913  tdd_init();
3914  callerid_init();
3916 
3917  if (ast_utils_init()) {
3918  printf("%s", term_quit());
3919  exit(1);
3920  }
3921 
3922  if (ast_tps_init()) {
3923  printf("%s", term_quit());
3924  exit(1);
3925  }
3926 
3927  if (ast_fd_init()) {
3928  printf("%s", term_quit());
3929  exit(1);
3930  }
3931 
3932  if (ast_pbx_init()) {
3933  printf("%s", term_quit());
3934  exit(1);
3935  }
3936 
3937  if (ast_event_init()) {
3938  printf("%s", term_quit());
3939  exit(1);
3940  }
3941 
3942 #ifdef TEST_FRAMEWORK
3943  if (ast_test_init()) {
3944  printf("%s", term_quit());
3945  exit(1);
3946  }
3947 #endif
3948 
3949  ast_aoc_cli_init();
3950 
3951  ast_makesocket();
3952  sigemptyset(&sigs);
3953  sigaddset(&sigs, SIGHUP);
3954  sigaddset(&sigs, SIGTERM);
3955  sigaddset(&sigs, SIGINT);
3956  sigaddset(&sigs, SIGPIPE);
3957  sigaddset(&sigs, SIGWINCH);
3958  pthread_sigmask(SIG_BLOCK, &sigs, NULL);
3959  sigaction(SIGURG, &urg_handler, NULL);
3960  signal(SIGINT, __quit_handler);
3961  signal(SIGTERM, __quit_handler);
3962  sigaction(SIGHUP, &hup_handler, NULL);
3963  sigaction(SIGPIPE, &ignore_sig_handler, NULL);
3964 
3965  /* ensure that the random number generators are seeded with a different value every time
3966  Asterisk is started
3967  */
3968  srand((unsigned int) getpid() + (unsigned int) time(NULL));
3969  initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
3970 
3971  if (init_logger()) { /* Start logging subsystem */
3972  printf("%s", term_quit());
3973  exit(1);
3974  }
3975 
3977 
3979 
3980  if (ast_timing_init()) {
3981  printf("%s", term_quit());
3982  exit(1);
3983  }
3984 
3985  if (ast_ssl_init()) {
3986  printf("%s", term_quit());
3987  exit(1);
3988  }
3989 
3990 #ifdef AST_XML_DOCS
3991  /* Load XML documentation. */
3993 #endif
3994 
3995  /* initialize the data retrieval API */
3996  if (ast_data_init()) {
3997  printf ("%s", term_quit());
3998  exit(1);
3999  }
4000 
4002 
4003  if ((moduleresult = load_modules(1))) { /* Load modules, pre-load only */
4004  printf("%s", term_quit());
4005  exit(moduleresult == -2 ? 2 : 1);
4006  }
4007 
4008  if (dnsmgr_init()) { /* Initialize the DNS manager */
4009  printf("%s", term_quit());
4010  exit(1);
4011  }
4012 
4013  ast_http_init(); /* Start the HTTP server, if needed */
4014 
4015  if (init_manager()) {
4016  printf("%s", term_quit());
4017  exit(1);
4018  }
4019 
4020  if (ast_cdr_engine_init()) {
4021  printf("%s", term_quit());
4022  exit(1);
4023  }
4024 
4025  if (ast_cel_engine_init()) {
4026  printf("%s", term_quit());
4027  exit(1);
4028  }
4029 
4031  printf("%s", term_quit());
4032  exit(1);
4033  }
4034 
4035  ast_dsp_init();
4036  ast_udptl_init();
4037 
4038  if (ast_image_init()) {
4039  printf("%s", term_quit());
4040  exit(1);
4041  }
4042 
4043  if (ast_file_init()) {
4044  printf("%s", term_quit());
4045  exit(1);
4046  }
4047 
4048  if (load_pbx()) {
4049  printf("%s", term_quit());
4050  exit(1);
4051  }
4052 
4053  if (ast_indications_init()) {
4054  printf("%s", term_quit());
4055  exit(1);
4056  }
4057 
4058  if (ast_features_init()) {
4059  printf("%s", term_quit());
4060  exit(1);
4061  }
4062 
4063  if (init_framer()) {
4064  printf("%s", term_quit());
4065  exit(1);
4066  }
4067 
4068  if (astdb_init()) {
4069  printf("%s", term_quit());
4070  exit(1);
4071  }
4072 
4073  if (ast_enum_init()) {
4074  printf("%s", term_quit());
4075  exit(1);
4076  }
4077 
4078  if (ast_cc_init()) {
4079  printf("%s", term_quit());
4080  exit(1);
4081  }
4082 
4083  if ((moduleresult = load_modules(0))) { /* Load modules */
4084  printf("%s", term_quit());
4085  exit(moduleresult == -2 ? 2 : 1);
4086  }
4087 
4088  /* loads the cli_permissoins.conf file needed to implement cli restrictions. */
4089  ast_cli_perms_init(0);
4090 
4091  ast_stun_init();
4092 
4094 
4095  /* We might have the option of showing a console, but for now just
4096  do nothing... */
4097  if (ast_opt_console && !option_verbose)
4098  ast_verbose(" ]\n");
4099  if (option_verbose || ast_opt_console)
4100  ast_verbose("%s", term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
4101  if (ast_opt_no_fork)
4102  consolethread = pthread_self();
4103 
4104  if (pipe(sig_alert_pipe))
4105  sig_alert_pipe[0] = sig_alert_pipe[1] = -1;
4106 
4107  ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
4108  manager_event(EVENT_FLAG_SYSTEM, "FullyBooted", "Status: Fully Booted\r\n");
4109 
4111 
4112  pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
4113 
4114 #if defined(__AST_DEBUG_MALLOC)
4116 #endif /* defined(__AST_DEBUG_MALLOC) */
4117 
4119  ast_cli_register_multiple(cli_asterisk_shutdown, ARRAY_LEN(cli_asterisk_shutdown));
4120  ast_cli_register_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
4122 
4124 
4125  if (ast_opt_console) {
4126  /* Console stuff now... */
4127  /* Register our quit function */
4128  char title[256];
4129 
4131 
4132  set_icon("Asterisk");
4133  snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
4134  set_title(title);
4135 
4136  el_set(el, EL_GETCFN, ast_el_read_char);
4137 
4138  for (;;) {
4139  if (sig_flags.need_quit || sig_flags.need_quit_handler) {
4140  quit_handler(0, SHUTDOWN_FAST, 0);
4141  break;
4142  }
4143  buf = (char *) el_gets(el, &num);
4144 
4145  if (!buf && write(1, "", 1) < 0)
4146  goto lostterm;
4147 
4148  if (buf) {
4149  if (buf[strlen(buf)-1] == '\n')
4150  buf[strlen(buf)-1] = '\0';
4151 
4152  consolehandler((char *)buf);
4153  } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
4154  strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
4155  /* Whoa, stdout disappeared from under us... Make /dev/null's */
4156  int fd;
4157  fd = open("/dev/null", O_RDWR);
4158  if (fd > -1) {
4159  dup2(fd, STDOUT_FILENO);
4160  dup2(fd, STDIN_FILENO);
4161  } else
4162  ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
4163  break;
4164  }
4165  }
4166  }
4167 
4168  monitor_sig_flags(NULL);
4169 
4170 lostterm:
4171  return 0;
4172 }
static void __ast_unregister_atexit(void(*func)(void))
Definition: asterisk.c:965
static int sig_alert_pipe[2]
Definition: asterisk.c:302
int ast_indications_init(void)
Load indications module.
Definition: indications.c:1169
static char * handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2090
A-Law to Signed linear conversion.
void ast_console_puts(const char *string)
Definition: asterisk.c:1222
static char * handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2070
const char * ast_config_AST_KEY_DIR
Definition: asterisk.c:265
int ast_utils_init(void)
Definition: utils.c:2193
static int show_version(void)
Definition: asterisk.c:2997
void ast_register_thread(char *name)
Definition: asterisk.c:401
static void * canary_thread(void *unused)
Definition: asterisk.c:3318
int64_t ast_mark(int, int start1_stop0)
Definition: asterisk.c:775
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
int ast_file_init(void)
Definition: file.c:1503
char ** ast_cli_completion_matches(const char *, const char *)
Generates a NULL-terminated array of strings that 1) begin with the string in the second parameter...
Definition: cli.c:2368
char run_user[PATH_MAX]
Definition: asterisk.c:249
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define DEFAULT_LOG_DIR
Definition: defaults.h:11
uint32_t version
static struct @220 sig_flags
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1077
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
void tdd_init(void)
Definition: tdd.c:95
static const char config_file[]
Definition: cdr_odbc.c:49
static char * handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2162
static void canary_exit(void)
Definition: asterisk.c:3347
const char * ast_build_user
Definition: buildinfo.c:34
static History * el_hist
Definition: asterisk.c:221
static const char config[]
Definition: cdr_csv.c:57
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static char ast_config_AST_CTL_GROUP[PATH_MAX]
Definition: asterisk.c:277
#define AST_MAX_CONNECTS
Definition: asterisk.c:158
const char * name
Definition: asterisk.c:692
#define VERBOSE_PREFIX_1
Definition: logger.h:41
int ast_realtime_enabled(void)
Check if there&#39;s any realtime engines loaded.
Definition: config.c:2601
static char * handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2110
int64_t ast_profile(int, int64_t)
Definition: asterisk.c:740
#define DEFAULT_CONFIG_FILE
Definition: defaults.h:6
char * strsep(char **str, const char *delims)
#define AST_CLI_COMPLETE_EOF
Definition: cli.h:51
void ast_autoservice_init(void)
Definition: autoservice.c:335
static int ast_makesocket(void)
Definition: asterisk.c:1460
int ast_image_init(void)
Initialize image stuff Initializes all the various image stuff. Basically just registers the cli stuf...
Definition: image.c:213
static struct sigaction ignore_sig_handler
Definition: asterisk.c:1037
static const char license_lines[]
Definition: asterisk.c:2220
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
int main(int argc, char *argv[])
void ast_register_file_version(const char *file, const char *version)
Register the version of a source code file with the core.
Definition: asterisk.c:318
void ast_builtins_init(void)
initialize the _full_cmd string in * each of the builtins.
Definition: cli.c:1880
#define COLOR_GRAY
Definition: term.h:48
static struct ast_cli_entry cli_asterisk[]
Definition: asterisk.c:2278
static char * handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2011
const char * ast_config_AST_DB
Definition: asterisk.c:268
#define ast_strdup(a)
Definition: astmm.h:109
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
#define DEFAULT_DATA_DIR
Definition: defaults.h:20
char data_dir[PATH_MAX]
Definition: asterisk.c:239
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:422
static struct sigaction urg_handler
Definition: asterisk.c:1566
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
Asterisk version information.
static ast_mutex_t safe_system_lock
Definition: asterisk.c:1041
#define DEFAULT_RUN_DIR
Definition: defaults.h:13
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
void ast_udptl_init(void)
Definition: udptl.c:1436
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
static char * handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2130
static char * show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2202
static int ast_el_read_history(char *)
Definition: asterisk.c:2825
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
int option_debug
Definition: asterisk.c:182
Device state management.
#define DEFAULT_DB
Definition: defaults.h:18
static char * handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Give an overview of system statistics.
Definition: asterisk.c:593
Call Event Logging API.
#define RESULT_SHOWUSAGE
Definition: cli.h:40
const char * ast_config_AST_MODULE_DIR
Definition: asterisk.c:258
#define DEFAULT_AGI_DIR
Definition: defaults.h:10
#define AST_DEFAULT_OPTIONS
Definition: options.h:102
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:14
#define DEFAULT_VAR_DIR
Definition: defaults.h:17
static char ast_config_AST_CTL_OWNER[PATH_MAX]
Definition: asterisk.c:276
#define NUMLOGLEVELS
Definition: logger.h:184
static char * handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:521
unsigned int need_reload
Definition: asterisk.c:304
Convenient Signal Processing routines.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define ast_set_flag(p, flag)
Definition: utils.h:70
static int remoteconsolehandler(char *s)
Definition: asterisk.c:1952
static int ast_all_zeros(char *s)
Definition: asterisk.c:1924
static const char * fix_header(char *outbuf, int maxout, const char *s, char *cmp)
Definition: asterisk.c:1882
#define VERBOSE_PREFIX_3
Definition: logger.h:43
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void destroy_match_list(char **match_list, int matches)
Definition: asterisk.c:2524
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. ...
Definition: pbx.c:870
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
static char * cli_complete(EditLine *editline, int ch)
Definition: asterisk.c:2642
char * ast_complete_source_filename(const char *partial, int n)
Definition: asterisk.c:357
static int multi_thread_safe
Definition: asterisk.c:298
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
#define WELCOME_MESSAGE
Welcome message when starting a CLI interface.
Definition: asterisk.c:162
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
void ast_begin_shutdown(int hangup)
Definition: channel.c:838
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
static void __remote_quit_handler(int num)
Definition: asterisk.c:1877
const char * ast_build_date
Definition: buildinfo.c:33
#define ASTERISK_PROMPT2
Definition: asterisk.c:2259
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define ast_FDMAX
Definition: select.h:41
char var_dir[PATH_MAX]
Definition: asterisk.c:238
UDPTL support for T.38.
static struct sigaction safe_system_prev_handler
Definition: asterisk.c:1045
int ast_tps_init(void)
static void network_verboser(const char *s)
Definition: asterisk.c:1229
const char * ast_build_os
Definition: buildinfo.c:32
Test Framework API.
#define COLOR_WHITE
Definition: term.h:61
static void _hup_handler(int num)
Definition: asterisk.c:1571
char module_dir[PATH_MAX]
Definition: asterisk.c:235
Definition: cli.h:146
static EditLine * el
Definition: asterisk.c:222
static struct profile_data * prof_data
Definition: asterisk.c:705
Configuration File Parser.
static char * _argv[256]
Definition: asterisk.c:282
int option_verbose
Definition: asterisk.c:181
int ast_features_init(void)
Definition: features.c:8336
int ast_xmldoc_load_documentation(void)
Load XML documentation. Provided by xmldoc.c.
Definition: xmldoc.c:1963
static char * levels[NUMLOGLEVELS]
Logging channels used in the Asterisk logging system.
Definition: logger.c:160
static int show_cli_help(void)
Definition: asterisk.c:3003
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
char key_dir[PATH_MAX]
Definition: asterisk.c:243
static char * cli_prompt(EditLine *editline)
Definition: asterisk.c:2397
static void _null_sig_handler(int sig)
NULL handler so we can collect the child exit status.
Definition: asterisk.c:1028
void ast_set_default_eid(struct ast_eid *eid)
Fill in an ast_eid with the default eid of this machine.
Definition: netsock.c:239
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
int ast_test_init(void)
Definition: test.c:941
int ast_cc_init(void)
Initialize CCSS.
Definition: ccss.c:4340
const char * ast_config_AST_RUN_DIR
Definition: asterisk.c:266
void ast_alaw_init(void)
To init the alaw to slinear conversion stuff, this needs to be run.
Definition: alaw.c:154
unsigned int need_quit
Definition: asterisk.c:305
#define ast_assert(a)
Definition: utils.h:738
void ast_module_shutdown(void)
Run the unload() callback for all loaded modules.
Definition: loader.c:513
static int ast_cli_display_match_list(char **matches, int len, int max)
Definition: asterisk.c:2594
#define ast_mutex_lock(a)
Definition: lock.h:155
const char * ast_config_AST_RUN_USER
Definition: asterisk.c:271
char * text
Definition: app_queue.c:1091
#define MAXHOSTNAMELEN
Definition: network.h:69
int uid
Definition: asterisk.c:205
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int64_t mark
Definition: asterisk.c:694
void ast_console_toggle_loglevel(int fd, int level, int state)
enables or disables logging of a specified level to the console fd specifies the index of the console...
Definition: asterisk.c:1136
int ast_http_init(void)
Definition: http.c:1319
int check_manager_enabled(void)
Check if AMI is enabled.
Definition: manager.c:1107
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
#define WIFEXITED(status)
Definition: private.h:105
int ast_dsp_init(void)
Load dsp settings from dsp.conf.
Definition: dsp.c:1885
I/O Management (derived from Cheops-NG)
#define COLOR_BRWHITE
Definition: term.h:62
static int ast_el_write_history(char *)
Definition: asterisk.c:2815
int value
Definition: syslog.c:39
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static int ast_tryconnect(void)
Definition: asterisk.c:1534
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: config.c:2499
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:431
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
Definition: asterisk.c:1062
int gid
Definition: asterisk.c:206
#define ast_opt_reconnect
Definition: options.h:119
#define ast_opt_console
Definition: options.h:107
void ast_console_toggle_mute(int fd, int silent)
mute or unmute a console from logging
Definition: asterisk.c:1159
const char * ast_build_hostname
Definition: buildinfo.c:29
int max_size
Definition: asterisk.c:701
int ast_get_termcols(int fd)
Definition: io.c:368
char defaultlanguage[]
Definition: asterisk.c:227
#define MAX_LANGUAGE
Definition: channel.h:138
static int mute
Definition: chan_alsa.c:135
Utility functions.
int args
This gets set in ast_cli_register()
Definition: cli.h:179
int option_maxfiles
Definition: asterisk.c:185
const char * ast_build_kernel
Definition: buildinfo.c:30
static void quit_handler(int num, shutdown_nice_t niceness, int restart)
Definition: asterisk.c:1687
#define WEXITSTATUS(status)
Definition: private.h:108
#define FD_ZERO(a)
Definition: select.h:49
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:426
const char * ast_config_AST_SYSTEM_NAME
Definition: asterisk.c:273
static char * handle_show_version_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list module versions.
Definition: asterisk.c:868
#define CONFIG_STATUS_FILEMISSING
Definition: config.h:50
static char * handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2050
int ast_cel_engine_init(void)
Definition: cel.c:860
static void _urg_handler(int num)
Urgent handler.
Definition: asterisk.c:1561
#define FD_SET(fd, fds)
Definition: select.h:58
uint64_t scale
Definition: asterisk.c:693
const char * ast_config_AST_RUN_GROUP
Definition: asterisk.c:272
Call Detail Record API.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
static void env_init(void)
Definition: asterisk.c:3381
char run_group[PATH_MAX]
Definition: asterisk.c:250
static void _child_handler(int sig)
Definition: asterisk.c:1592
Support for Private Asterisk HTTP Servers.
void __ast_mm_init_phase_1(void)
const char * ast_build_machine
Definition: buildinfo.c:31
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:703
const char * ast_config_AST_CONFIG_FILE
Definition: asterisk.c:257
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1431
static void ast_readconfig(void)
Definition: asterisk.c:3042
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int64_t events
Definition: asterisk.c:696
static pthread_t mon_sig_flags
Definition: asterisk.c:295
static char * handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2030
General Asterisk channel definitions for image handling.
u-Law to Signed linear conversion
Generic Advice of Charge encode and decode routines.
const char * value
Definition: config.h:79
static void * listener(void *unused)
Definition: asterisk.c:1383
void ast_unregister_thread(void *id)
Definition: asterisk.c:416
void close_logger(void)
Definition: logger.c:1160
static int ast_el_sort_compare(const void *i1, const void *i2)
Definition: asterisk.c:2584
char spool_dir[PATH_MAX]
Definition: asterisk.c:236
void callerid_init(void)
CallerID Initialization.
Definition: callerid.c:116
#define VERBOSE_PREFIX_4
Definition: logger.h:44
General Asterisk PBX channel definitions.
int ast_term_init(void)
Definition: term.c:87
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: asterisk.c:1003
static void __quit_handler(int num)
Definition: asterisk.c:1864
int ast_register_verbose(void(*verboser)(const char *string)) attribute_warn_unused_result
Definition: logger.c:1577
long option_minmemfree
Definition: asterisk.c:187
#define VERBOSE_PREFIX_2
Definition: logger.h:42
Asterisk file paths, configured in asterisk.conf.
DNS and ENUM functions.
void ast_unregister_atexit(void(*func)(void))
Unregister a function registered with ast_register_atexit().
Definition: asterisk.c:1008
const char * ast_config_AST_AGI_DIR
Definition: asterisk.c:264
const int fd
Definition: cli.h:153
#define EL_BUF_SIZE
#define AST_PTHREADT_NULL
Definition: lock.h:65
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
static void set_title(char *text)
Set an X-term or screen title.
Definition: asterisk.c:1636
const char * ast_config_AST_PID
Definition: asterisk.c:269
char * term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
Write a color sequence to a string.
Definition: term.c:264
int ast_language_is_prefix
Definition: file.c:63
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:155
#define AST_CACHE_DIR_LEN
Definition: options.h:32
Scheduler Routines (derived from cheops)
static struct sigaction hup_handler
Definition: asterisk.c:1587
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
static int ast_select(int nfds, ast_fdset *rfds, ast_fdset *wfds, ast_fdset *efds, struct timeval *tvp)
Waits for activity on a group of channels.
Definition: select.h:81
char db_path[PATH_MAX]
Definition: asterisk.c:246
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
int init_logger(void)
Definition: logger.c:1127
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: netsock.c:305
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
struct timeval ast_lastreloadtime
Definition: asterisk.c:219
static const char warranty_lines[]
Definition: asterisk.c:2177
A set of macros to manage forward-linked lists.
const char * name
Definition: config.h:77
ast_cli_command
calling arguments for new-style handlers.
Definition: cli.h:145
void(* func)(void)
Definition: asterisk.c:211
static int ast_socket
Definition: asterisk.c:197
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct console consoles[AST_MAX_CONNECTS]
Definition: asterisk.c:225
char monitor_dir[PATH_MAX]
Definition: asterisk.c:237
int ast_aoc_cli_init(void)
enable aoc cli options
Definition: aoc.c:1612
struct ast_atexit::@221 list
int register_config_cli(void)
Exposed initialization method for core process.
Definition: config.c:3145
Core PBX routines and definitions.
shutdown_nice_t
Definition: asterisk.c:283
int ast_enum_init(void)
Definition: enum.c:1006
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1650
struct ast_flags ast_compat
Definition: asterisk.c:179
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
static shutdown_nice_t shuttingdown
Definition: asterisk.c:292
Wrapper for network related headers, masking differences between various operating systems...
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:290
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Definition: term.c:184
int mute
Definition: asterisk.c:204
const char *const * argv
Definition: cli.h:155
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
Definition: asterisk.c:710
const char * ast_config_AST_DATA_DIR
Definition: asterisk.c:262
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static pthread_t consolethread
Definition: asterisk.c:294
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_cdr_engine_term(void)
Definition: cdr.c:1663
#define COLOR_BLACK
Definition: term.h:47
static char canary_filename[128]
Definition: asterisk.c:297
int ast_device_state_engine_init(void)
Initialize the device state engine in separate thread.
Definition: devicestate.c:747
int p[2]
Definition: asterisk.c:202
static struct _cfg_paths cfg_paths
Definition: asterisk.c:254
void ast_ulaw_init(void)
Set up mu-law conversion table.
Definition: ulaw.c:175
int is_cleanup
Definition: asterisk.c:212
#define LOG_ERROR
Definition: logger.h:155
static void consolehandler(char *s)
Definition: asterisk.c:1934
static void run_startup_commands(void)
Definition: asterisk.c:3353
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
Definition: stun.c:508
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static int fdsend(int fd, const char *s)
Definition: asterisk.c:1016
static char randompool[256]
Definition: asterisk.c:300
static char * handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Give an overview of core settings.
Definition: asterisk.c:436
#define PF_LOCAL
Definition: asterisk.c:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
const char * ast_config_AST_CONFIG_DIR
Definition: asterisk.c:256
double option_maxload
Definition: asterisk.c:183
TTY/TDD Generation support.
#define ast_opt_remote
Definition: options.h:110
unsigned int ast_FD_SETSIZE
Definition: poll.c:86
int setenv(const char *name, const char *value, int overwrite)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int ast_el_read_char(EditLine *editline, char *cp)
Definition: asterisk.c:2296
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static void * netconsole(void *vconsole)
Definition: asterisk.c:1295
#define DEFINE_PROFILE_MIN_MAX_VALUES
Definition: asterisk.c:791
const char * ast_config_AST_LOG_DIR
Definition: asterisk.c:263
int astobj2_init(void)
Definition: astobj2.c:1150
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define ast_opt_override_config
Definition: options.h:118
int ast_event_init(void)
Definition: event.c:1819
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
static char * remotehostname
Definition: asterisk.c:223
static int ast_consock
Definition: asterisk.c:198
int errno
char pid_path[PATH_MAX]
Definition: asterisk.c:247
char config_dir[PATH_MAX]
Definition: asterisk.c:234
static const char name[]
static void set_icon(char *text)
Definition: asterisk.c:1642
int ast_module_reload(const char *name)
Reload asterisk modules.
Definition: loader.c:721
static void ast_remotecontrol(char *data)
Definition: asterisk.c:2852
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
const char * ast_config_AST_MONITOR_DIR
Definition: asterisk.c:260
void ast_cancel_shutdown(void)
Cancel a shutdown in progress.
Definition: channel.c:859
static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
read() function supporting the reception of user credentials.
Definition: asterisk.c:1246
#define DEFAULT_KEY_DIR
Definition: defaults.h:21
static char * handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:839
void pbx_live_dangerously(int new_live_dangerously)
Enable/disable the execution of &#39;dangerous&#39; functions from external protocols (AMI, etc.).
Definition: pbx.c:4059
Call Completion Supplementary Services API.
static char ast_config_AST_CTL[PATH_MAX]
Definition: asterisk.c:278
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: app.c:2237
static char * handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:804
static struct ast_format f[]
Definition: format_g726.c:181
Asterisk XML Documentation API.
const char * word
Definition: cli.h:157
#define DEFAULT_PID
Definition: defaults.h:15
void ast_console_puts_mutable(const char *string, int level)
log the string to the console, and all attached console clients
Definition: asterisk.c:1199
static int canary_pid
Definition: asterisk.c:296
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
#define ast_opt_always_fork
Definition: options.h:124
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
int levels[NUMLOGLEVELS]
Definition: asterisk.c:207
static struct sigaction child_handler
Definition: asterisk.c:1607
static void main_atexit(void)
Definition: asterisk.c:3410
#define AST_BUILDOPTS
Definition: buildopts.h:24
#define DEFAULT_TMP_DIR
Definition: defaults.h:24
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
int check_webmanager_enabled(void)
Check if AMI/HTTP is enabled.
Definition: manager.c:1112
static unsigned int safe_system_level
Keep track of how many threads are currently trying to wait*() on a child process.
Definition: asterisk.c:1044
Structure used to handle boolean flags.
Definition: utils.h:200
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int64_t value
Definition: asterisk.c:695
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:414
const char * usage
Definition: cli.h:171
#define AF_LOCAL
Definition: asterisk.c:154
char record_cache_dir[AST_CACHE_DIR_LEN]
Definition: asterisk.c:195
struct ast_eid ast_eid_default
Global EID.
Definition: asterisk.c:192
#define sched_setscheduler
Definition: asterisk.h:44
struct timeval ast_startuptime
Definition: asterisk.c:218
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:436
#define CLI_SUCCESS
Definition: cli.h:43
int ast_ssl_init(void)
Definition: ssl.c:77
Definition: asterisk.c:691
#define DEFAULT_SPOOL_DIR
Definition: defaults.h:23
void clean_time_zones(void)
Definition: localtime.c:1421
int init_framer(void)
Definition: frame.c:995
int ast_pbx_init(void)
Definition: pbx.c:11407
char run_dir[PATH_MAX]
Definition: asterisk.c:242
int ast_cli_command_multiple_full(int uid, int gid, int fd, size_t size, const char *s)
Executes multiple CLI commands Interpret strings separated by NULL and execute each one...
Definition: cli.c:2585
#define ast_opt_exec
Definition: options.h:111
struct ast_flags ast_options
Definition: asterisk.c:178
static void ast_network_puts_mutable(const char *string, int level)
log the string to all attached console clients
Definition: asterisk.c:1182
static pthread_t lthread
Definition: asterisk.c:1234
void __ast_mm_init_phase_2(void)
pid_t ast_mainpid
Definition: asterisk.c:199
void threadstorage_init(void)
Definition: threadstorage.c:35
static int fdprint(int fd, const char *s)
Definition: asterisk.c:1022
int load_modules(unsigned int)
Definition: loader.c:1072
Standard Command Line Interface.
static int ast_el_initialize(void)
Definition: asterisk.c:2767
#define ast_calloc(a, b)
Definition: astmm.h:82
#define DEFAULT_LANGUAGE
Definition: asterisk.h:39
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
void ast_set_lock_type(enum AST_LOCK_TYPE type)
Set the type of locks used by ast_lock_path()
Definition: app.c:1647
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct profile_entry e[0]
Definition: asterisk.c:702
#define __LOG_VERBOSE
Definition: logger.h:165
char socket_path[PATH_MAX]
Definition: asterisk.c:248
int ast_cdr_engine_init(void)
Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
Definition: cdr.c:1646
int dnsmgr_init(void)
Definition: dnsmgr.c:417
static int register_atexit(void(*func)(void), int is_cleanup)
Definition: asterisk.c:979
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
const int pos
Definition: cli.h:158
#define ast_realloc(a, b)
Definition: astmm.h:103
#define FORMAT
char agi_dir[PATH_MAX]
Definition: asterisk.c:241
const char * ast_config_AST_SOCKET
Definition: asterisk.c:270
void dnsmgr_start_refresh(void)
Definition: dnsmgr.c:291
#define MAX_HISTORY_COMMAND_LENGTH
Definition: asterisk.c:2802
#define setpriority
Definition: asterisk.h:43
pthread_t t
Definition: asterisk.c:203
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int can_safely_quit(shutdown_nice_t niceness, int restart)
Definition: asterisk.c:1696
static int total
Definition: res_adsi.c:967
int init_manager(void)
Called by Asterisk initialization.
Definition: manager.c:7262
static char * handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:1980
#define DEFAULT_MODULE_DIR
Definition: defaults.h:9
Handy terminal functions for vt* terms.
enum queue_result id
Definition: app_queue.c:1090
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX]
Definition: asterisk.c:275
struct ast_variable * next
Definition: config.h:82
int ast_timing_init(void)
Definition: timing.c:310
int ast_data_init(void)
Definition: data.c:3297
static struct sigaction null_sig_handler
Definition: asterisk.c:1032
int ast_undestroyed_channels(void)
Definition: channel.c:853
void ast_channels_init(void)
Definition: channel.c:8221
static char * show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2239
int check_cdr_enabled(void)
Return TRUE if CDR subsystem is enabled.
Definition: cdr.c:120
#define DEFAULT_CONFIG_DIR
Definition: defaults.h:8
static struct ast_str * prompt
Definition: asterisk.c:2395
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
unsigned int need_quit_handler
Definition: asterisk.c:306
char config_file[PATH_MAX]
Definition: asterisk.c:245
#define DEFAULT_SOCKET
Definition: defaults.h:14
const char * ast_file_version_find(const char *file)
Find version for given module name.
Definition: asterisk.c:376
static int restartnow
Definition: asterisk.c:293
int fd
Definition: asterisk.c:201
static int ast_el_add_history(char *)
Definition: asterisk.c:2804
char log_dir[PATH_MAX]
Definition: asterisk.c:240
static void ast_network_puts(const char *string)
write the string to all attached console clients
Definition: asterisk.c:1209
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
#define RESULT_SUCCESS
Definition: cli.h:39
#define ast_malloc(a)
Definition: astmm.h:91
#define ast_opt_hide_connect
Definition: options.h:130
Asterisk module definitions.
#define ASTERISK_PROMPT
Definition: asterisk.c:2257
int ast_fd_init(void)
Definition: astfd.c:289
const char * ast_config_AST_VAR_DIR
Definition: asterisk.c:261
char * term_end(void)
Definition: term.c:365
#define ast_opt_mute
Definition: options.h:125
static struct ast_cli_entry cli_asterisk_shutdown[]
Shutdown Asterisk CLI commands.
Definition: asterisk.c:2269
int option_maxcalls
Definition: asterisk.c:184
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:848
#define ast_opt_no_fork
Definition: options.h:105
#define ast_opt_dump_core
Definition: options.h:115
static void print_intro_message(const char *runuser, const char *rungroup)
Definition: asterisk.c:3393
int load_pbx(void)
Definition: pbx.c:10996
static char ** ast_el_strtoarr(char *buf)
Definition: asterisk.c:2536
int getloadavg(double *list, int nelem)
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
void ast_process_pending_reloads(void)
Process reload requests received during startup.
Definition: loader.c:656
static void set_ulimit(int value)
Set maximum open files.
Definition: asterisk.c:1613
char system_name[128]
Definition: asterisk.c:251
static void really_quit(int num, shutdown_nice_t niceness, int restart)
Definition: asterisk.c:1763
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
int astdb_init(void)
Definition: db.c:880
static void * monitor_sig_flags(void *unused)
Definition: asterisk.c:3292
void ast_replace_sigchld(void)
Replace the SIGCHLD handler.
Definition: asterisk.c:1047
int ast_cli_perms_init(int reload)
Definition: cli.c:1752
static void ast_run_atexits(int run_cleanups)
Definition: asterisk.c:951
jack_status_t status
Definition: app_jack.c:143
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define ast_opt_high_priority
Definition: options.h:108
static void console_verboser(const char *s)
Definition: asterisk.c:1899
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
#define ast_mutex_unlock(a)
Definition: lock.h:156
static char hostname[MAXHOSTNAMELEN]
Definition: logger.c:91
static __inline uint64_t rdtsc(void)
Definition: asterisk.c:769
void ast_unregister_file_version(const char *file)
Unregister a source code file from the core.
Definition: asterisk.c:339
static char prefix[MAX_PREFIX]
Definition: http.c:107
int read_config_maps(void)
Exposed re-initialization method for core process.
Definition: config.c:2298
char * term_quit(void)
Definition: term.c:370