Asterisk - The Open Source Telephony Project  GIT-master-a24979a
asterisk.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2018, 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 Welcome
25  *
26  * This documentation created by the Doxygen project clearly explains the
27  * internals of the Asterisk software. This documentation contains basic
28  * examples, developer documentation, support information, and information
29  * for upgrading.
30  *
31  * \section community Community
32  * Asterisk is a big project and has a busy community. Look at the
33  * resources for questions and stick around to help answer questions.
34  * \li \ref asterisk_community_resources
35  *
36  * \par Developer Documentation for Asterisk
37  *
38  * This is the main developer documentation for Asterisk. It is
39  * generated by running "make progdocs" from the Asterisk source tree.
40  *
41  * In addition to the information available on the Asterisk source code,
42  * please see the appendices for information on coding guidelines,
43  * release management, commit policies, and more.
44  *
45  * \arg \ref AsteriskArchitecture
46  *
47  * \par Additional documentation
48  * \arg \ref Licensing
49  * \arg \ref DevDoc
50  * \arg \ref configuration_file
51  * \arg \ref channel_drivers
52  * \arg \ref applications
53  *
54  * \section copyright Copyright and Author
55  *
56  * Copyright (C) 1999 - 2021, Sangoma Technologies Corporation.
57  * Asterisk is a <a href="https://cdn.sangoma.com/wp-content/uploads/Sangoma-Trademark-Policy.pdf">registered trademark</a>
58  * of <a rel="nofollow" href="http://www.sangoma.com">Sangoma Technologies Corporation</a>.
59  *
60  * \author Mark Spencer <markster@digium.com>
61  *
62  * See http://www.asterisk.org for more information about
63  * the Asterisk project. Please do not directly contact
64  * any of the maintainers of this project for assistance;
65  * the project provides a web site, mailing lists, and IRC
66  * channels for your use.
67  *
68  */
69 
70 /*!
71  * \page asterisk_community_resources Asterisk Community Resources
72  * \par Websites
73  * \li http://www.asterisk.org Asterisk Homepage
74  * \li http://wiki.asterisk.org Asterisk Wiki
75  *
76  * \par Mailing Lists
77  * \par
78  * All lists: http://lists.digium.com/mailman/listinfo
79  * \li aadk-commits SVN commits to the AADK repository
80  * \li asterisk-addons-commits SVN commits to the Asterisk addons project
81  * \li asterisk-announce [no description available]
82  * \li asterisk-biz Commercial and Business-Oriented Asterisk Discussion
83  * \li Asterisk-BSD Asterisk on BSD discussion
84  * \li asterisk-bugs [no description available]
85  * \li asterisk-commits SVN commits to the Asterisk project
86  * \li asterisk-dev Asterisk Developers Mailing List
87  * \li asterisk-doc Discussions regarding The Asterisk Documentation Project
88  * \li asterisk-embedded Asterisk Embedded Development
89  * \li asterisk-gui Asterisk GUI project discussion
90  * \li asterisk-gui-commits SVN commits to the Asterisk-GUI project
91  * \li asterisk-ha-clustering Asterisk High Availability and Clustering List - Non-Commercial Discussion
92  * \li Asterisk-i18n Discussion of Asterisk internationalization
93  * \li asterisk-r2 [no description available]
94  * \li asterisk-scf-commits Commits to the Asterisk SCF project code repositories
95  * \li asterisk-scf-committee Asterisk SCF Steering Committee discussions
96  * \li asterisk-scf-dev Asterisk SCF Developers Mailing List
97  * \li asterisk-scf-wiki-changes Changes to the Asterisk SCF space on wiki.asterisk.org
98  * \li asterisk-security Asterisk Security Discussion
99  * \li asterisk-speech-rec Use of speech recognition in Asterisk
100  * \li asterisk-ss7 [no description available]
101  * \li asterisk-users Asterisk Users Mailing List - Non-Commercial Discussion
102  * \li asterisk-video Development discussion of video media support in Asterisk
103  * \li asterisk-wiki-changes Changes to the Asterisk space on wiki.asterisk.org
104  * \li asterisknow AsteriskNOW Discussion
105  * \li dahdi-commits SVN commits to the DAHDI project
106  * \li digium-announce Digium Product Announcements
107  * \li Dundi Distributed Universal Number Discovery
108  * \li libiax2-commits SVN commits to the libiax2 project
109  * \li libpri-commits SVN commits to the libpri project
110  * \li libss7-commits SVN commits to the libss7 project
111  * \li svn-commits SVN commits to the Digium repositories
112  * \li Test-results Results from automated testing
113  * \li thirdparty-commits SVN commits to the Digium third-party software repository
114  * \li zaptel-commits SVN commits to the Zaptel project
115  *
116  * \par Forums
117  * \li Forums are located at http://forums.asterisk.org/
118  *
119  * \par IRC
120  * \par
121  * Use https://libera.chat IRC server to connect with Asterisk
122  * developers and users in realtime.
123  *
124  * \li \verbatim #asterisk \endverbatim Asterisk Users Room
125  * \li \verbatim #asterisk-dev \endverbatim Asterisk Developers Room
126  *
127  * \par More
128  * \par
129  * If you would like to add a resource to this list please create an issue
130  * on the issue tracker with a patch.
131  */
132 
133 /*! \file
134  * \brief Top level source file for Asterisk - the Open Source PBX.
135  * Implementation of PBX core functions and CLI interface.
136  */
137 
138 /*! \li \ref asterisk.c uses the configuration file \ref asterisk.conf
139  * \addtogroup configuration_file
140  */
141 
142 /*! \page asterisk.conf asterisk.conf
143  * \verbinclude asterisk.conf.sample
144  */
145 
146 /*** MODULEINFO
147  <support_level>core</support_level>
148  ***/
149 
150 #include "asterisk.h"
151 
152 #include "asterisk/_private.h"
153 
154 #undef sched_setscheduler
155 #undef setpriority
156 #include <sys/time.h>
157 #include <fcntl.h>
158 #include <signal.h>
159 #include <sched.h>
160 #include <sys/un.h>
161 #include <sys/wait.h>
162 #include <ctype.h>
163 #include <sys/resource.h>
164 #include <grp.h>
165 #include <pwd.h>
166 #include <sys/stat.h>
167 #if defined(HAVE_SYSINFO)
168 #include <sys/sysinfo.h>
169 #elif defined(HAVE_SYSCTL)
170 #include <sys/param.h>
171 #include <sys/sysctl.h>
172 #include <sys/vmmeter.h>
173 #if defined(__FreeBSD__) || defined(__DragonFly__)
174 #include <vm/vm_param.h>
175 #endif
176 #if defined(HAVE_SWAPCTL)
177 #include <sys/swap.h>
178 #endif
179 #endif
180 #include <regex.h>
181 #include <histedit.h>
182 
183 #if defined(SOLARIS)
184 int daemon(int, int); /* defined in libresolv of all places */
185 #include <sys/loadavg.h>
186 #endif
187 
188 #ifdef linux
189 #include <sys/prctl.h>
190 #ifdef HAVE_CAP
191 #include <sys/capability.h>
192 #endif /* HAVE_CAP */
193 #endif /* linux */
194 
195 /* we define here the variables so to better agree on the prototype */
196 #include "asterisk/paths.h"
197 #include "asterisk/network.h"
198 #include "asterisk/cli.h"
199 #include "asterisk/channel.h"
200 #include "asterisk/translate.h"
201 #include "asterisk/pickup.h"
202 #include "asterisk/acl.h"
203 #include "asterisk/ulaw.h"
204 #include "asterisk/alaw.h"
205 #include "asterisk/callerid.h"
206 #include "asterisk/image.h"
207 #include "asterisk/tdd.h"
208 #include "asterisk/term.h"
209 #include "asterisk/manager.h"
210 #include "asterisk/cdr.h"
211 #include "asterisk/pbx.h"
212 #include "asterisk/app.h"
213 #include "asterisk/mwi.h"
214 #include "asterisk/lock.h"
215 #include "asterisk/utils.h"
216 #include "asterisk/file.h"
217 #include "asterisk/io.h"
218 #include "asterisk/config.h"
219 #include "asterisk/ast_version.h"
220 #include "asterisk/linkedlists.h"
221 #include "asterisk/devicestate.h"
222 #include "asterisk/presencestate.h"
223 #include "asterisk/module.h"
224 #include "asterisk/buildinfo.h"
225 #include "asterisk/xmldoc.h"
226 #include "asterisk/poll-compat.h"
227 #include "asterisk/test.h"
228 #include "asterisk/rtp_engine.h"
229 #include "asterisk/format.h"
230 #include "asterisk/aoc.h"
231 #include "asterisk/uuid.h"
232 #include "asterisk/sorcery.h"
233 #include "asterisk/bucket.h"
234 #include "asterisk/stasis.h"
235 #include "asterisk/json.h"
237 #include "asterisk/stasis_system.h"
239 #include "asterisk/endpoints.h"
240 #include "asterisk/codec.h"
241 #include "asterisk/format_cache.h"
242 #include "asterisk/media_cache.h"
243 #include "asterisk/astdb.h"
244 #include "asterisk/options.h"
245 #include "asterisk/utf8.h"
246 
247 #include "../defaults.h"
248 
249 /*** DOCUMENTATION
250  <managerEvent language="en_US" name="FullyBooted">
251  <managerEventInstance class="EVENT_FLAG_SYSTEM">
252  <synopsis>Raised when all Asterisk initialization procedures have finished.</synopsis>
253  <syntax>
254  <parameter name="Status">
255  <para>Informational message</para>
256  </parameter>
257  <parameter name="Uptime">
258  <para>Seconds since start</para>
259  </parameter>
260  <parameter name="LastReload">
261  <para>Seconds since last reload</para>
262  </parameter>
263  </syntax>
264  </managerEventInstance>
265  </managerEvent>
266  <managerEvent language="en_US" name="Shutdown">
267  <managerEventInstance class="EVENT_FLAG_SYSTEM">
268  <synopsis>Raised when Asterisk is shutdown or restarted.</synopsis>
269  <syntax>
270  <parameter name="Shutdown">
271  <para>Whether the shutdown is proceeding cleanly (all channels
272  were hungup successfully) or uncleanly (channels will be
273  terminated)</para>
274  <enumlist>
275  <enum name="Uncleanly"/>
276  <enum name="Cleanly"/>
277  </enumlist>
278  </parameter>
279  <parameter name="Restart">
280  <para>Whether or not a restart will occur.</para>
281  <enumlist>
282  <enum name="True"/>
283  <enum name="False"/>
284  </enumlist>
285  </parameter>
286  </syntax>
287  </managerEventInstance>
288  </managerEvent>
289  ***/
290 
291 #ifndef AF_LOCAL
292 #define AF_LOCAL AF_UNIX
293 #define PF_LOCAL PF_UNIX
294 #endif
295 
296 #define AST_MAX_CONNECTS 128
297 #define NUM_MSGS 64
298 
299 /*! Displayed copyright tag */
300 #define COPYRIGHT_TAG "Copyright (C) 1999 - 2021, Sangoma Technologies Corporation and others."
301 
302 /*! \brief Welcome message when starting a CLI interface */
303 #define WELCOME_MESSAGE \
304  ast_verbose("Asterisk %s, " COPYRIGHT_TAG "\n" \
305  "Created by Mark Spencer <markster@digium.com>\n" \
306  "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
307  "This is free software, with components licensed under the GNU General Public\n" \
308  "License version 2 and other licenses; you are welcome to redistribute it under\n" \
309  "certain conditions. Type 'core show license' for details.\n" \
310  "=========================================================================\n", ast_get_version()) \
311 
312 static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
313 static int ast_socket_is_sd = 0; /*!< Is socket activation responsible for ast_socket? */
314 static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
316 struct console {
317  int fd; /*!< File descriptor */
318  int p[2]; /*!< Pipe */
319  pthread_t t; /*!< Thread of handler */
320  int mute; /*!< Is the console muted for logs */
321  int uid; /*!< Remote user ID. */
322  int gid; /*!< Remote group ID. */
323  int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */
324  /*! Verbosity level of this console. */
326 };
327 
328 struct ast_atexit {
329  void (*func)(void);
332 };
333 
335 
336 struct timeval ast_startuptime;
337 struct timeval ast_lastreloadtime;
338 
339 static History *el_hist;
340 static EditLine *el;
341 static char *remotehostname;
342 
344 
345 static int ast_el_add_history(const char *);
346 static int ast_el_read_history(const char *);
347 static int ast_el_write_history(const char *);
348 
349 static void ast_el_read_default_histfile(void);
350 static void ast_el_write_default_histfile(void);
351 
352 static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup);
353 
354 static char *_argv[256];
355 
356 typedef enum {
357  /*! Normal operation */
359  /*! Committed to shutting down. Final phase */
361  /*! Committed to shutting down. Initial phase */
363  /*!
364  * Valid values for quit_handler() niceness below.
365  * These shutdown/restart levels can be cancelled.
366  *
367  * Remote console exit right now
368  */
370  /*! core stop/restart now */
372  /*! core stop/restart gracefully */
374  /*! core stop/restart when convenient */
377 
379 
380 /*! Prevent new channel allocation for shutdown. */
381 static int shutdown_pending;
382 
383 static int restartnow;
384 static pthread_t consolethread = AST_PTHREADT_NULL;
385 static pthread_t mon_sig_flags;
386 static int canary_pid = 0;
387 static char canary_filename[128];
388 static int multi_thread_safe;
389 
390 static char randompool[256];
391 
392 #ifdef HAVE_CAP
393 static cap_t child_cap;
394 #endif
395 
396 static int sig_alert_pipe[2] = { -1, -1 };
397 static struct {
398  unsigned int need_reload:1;
399  unsigned int need_quit:1;
400  unsigned int need_quit_handler:1;
401  unsigned int need_el_end:1;
403 
404 #if !defined(LOW_MEMORY)
407  char *name;
408  pthread_t id;
409  int lwp;
410 };
411 
413 
415 {
416  struct thread_list_t *new = ast_calloc(1, sizeof(*new));
417 
418  if (!new)
419  return;
420 
422  new->id = pthread_self();
423  new->lwp = ast_get_tid();
424  new->name = name; /* steal the allocated memory for the thread name */
426  AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
428 }
429 
430 void ast_unregister_thread(void *id)
431 {
432  struct thread_list_t *x;
433 
436  if ((void *) x->id == id) {
438  break;
439  }
440  }
443  if (x) {
444  ast_free(x->name);
445  ast_free(x);
446  }
447 }
448 
449 /*! \brief Print the contents of a file */
450 static int print_file(int fd, char *desc, const char *filename)
451 {
452  FILE *f;
453  char c;
454  if (!(f = fopen(filename, "r"))) {
455  return -1;
456  }
457  ast_cli(fd, "%s", desc);
458  while ((c = fgetc(f)) != EOF) {
459  ast_cli(fd, "%c", c);
460  }
461  fclose(f);
462  /* no need for trailing new line, the file already has one */
463  return 0;
464 }
465 
466 /*! \brief Give an overview of core settings */
467 static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
468 {
469  char buf[BUFSIZ];
470  struct ast_tm tm;
471  char eid_str[128];
472  struct rlimit limits;
473  char pbx_uuid[AST_UUID_STR_LEN];
474 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
475  char dir[PATH_MAX];
476 #endif
477 
478  switch (cmd) {
479  case CLI_INIT:
480  e->command = "core show settings";
481  e->usage = "Usage: core show settings\n"
482  " Show core misc settings";
483  return NULL;
484  case CLI_GENERATE:
485  return NULL;
486  }
487 
488  ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
489  ast_pbx_uuid_get(pbx_uuid, sizeof(pbx_uuid));
490 
491  ast_cli(a->fd, "\nPBX Core settings\n");
492  ast_cli(a->fd, "-----------------\n");
493  ast_cli(a->fd, " Version: %s\n", ast_get_version());
494  ast_cli(a->fd, " Build Options: %s\n", S_OR(ast_get_build_opts(), "(none)"));
496  ast_cli(a->fd, " Maximum calls: %d (Current %d)\n", ast_option_maxcalls, ast_active_channels());
497  else
498  ast_cli(a->fd, " Maximum calls: Not set\n");
499 
500  if (getrlimit(RLIMIT_NOFILE, &limits)) {
501  ast_cli(a->fd, " Maximum open file handles: Error because of %s\n", strerror(errno));
502  } else if (limits.rlim_cur == RLIM_INFINITY) {
503  ast_cli(a->fd, " Maximum open file handles: Unlimited\n");
504  } else if (limits.rlim_cur < ast_option_maxfiles) {
505  ast_cli(a->fd, " Maximum open file handles: %d (is) %d (requested)\n", (int) limits.rlim_cur, ast_option_maxfiles);
506  } else {
507  ast_cli(a->fd, " Maximum open file handles: %d\n", (int) limits.rlim_cur);
508  }
509 
510  ast_cli(a->fd, " Root console verbosity: %d\n", option_verbose);
511  ast_cli(a->fd, " Current console verbosity: %d\n", ast_verb_console_get());
512  ast_cli(a->fd, " Debug level: %d\n", option_debug);
513  ast_cli(a->fd, " Trace level: %d\n", option_trace);
514  ast_cli(a->fd, " Dump core on crash: %s\n", ast_opt_dump_core ? "Yes" : "No");
515  print_file(a->fd, " Core dump file: ", "/proc/sys/kernel/core_pattern");
516  ast_cli(a->fd, " Maximum load average: %lf\n", ast_option_maxload);
517 #if defined(HAVE_SYSINFO)
518  ast_cli(a->fd, " Minimum free memory: %ld MB\n", option_minmemfree);
519 #endif
520  if (ast_localtime(&ast_startuptime, &tm, NULL)) {
521  ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
522  ast_cli(a->fd, " Startup time: %s\n", buf);
523  }
524  if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
525  ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
526  ast_cli(a->fd, " Last reload time: %s\n", buf);
527  }
528  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);
529  ast_cli(a->fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
530  ast_cli(a->fd, " Entity ID: %s\n", eid_str);
531  ast_cli(a->fd, " PBX UUID: %s\n", pbx_uuid);
532  ast_cli(a->fd, " Default language: %s\n", ast_defaultlanguage);
533  ast_cli(a->fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
534  ast_cli(a->fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
535 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
536 #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
537 #define eaccess euidaccess
538 #endif
539  if (!getcwd(dir, sizeof(dir))) {
540  if (eaccess(dir, R_OK | X_OK | F_OK)) {
541  ast_cli(a->fd, " Running directory: %s\n", "Unable to access");
542  } else {
543  ast_cli(a->fd, " Running directory: %s (%s)\n", dir, "Unable to access");
544  }
545  } else {
546  ast_cli(a->fd, " Running directory: %s\n", dir);
547  }
548 #endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
549  ast_cli(a->fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
550  ast_cli(a->fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
551  ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
552  ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
553  ast_cli(a->fd, " Generic PLC on equal codecs: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC_ON_EQUAL_CODECS) ? "Enabled" : "Disabled");
554  ast_cli(a->fd, " Hide Msg Chan AMI events: %s\n", ast_opt_hide_messaging_ami_events ? "Enabled" : "Disabled");
555  ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration);
556 #if !defined(LOW_MEMORY)
557  ast_cli(a->fd, " Cache media frames: %s\n", ast_opt_cache_media_frames ? "Enabled" : "Disabled");
558 #endif
559  ast_cli(a->fd, " RTP use dynamic payloads: %u\n", ast_option_rtpusedynamic);
560 
562  ast_cli(a->fd, " RTP dynamic payload types: %u,%u-%u\n",
566  ast_cli(a->fd, " RTP dynamic payload types: %u-%u,%u-%u\n",
569  } else {
570  ast_cli(a->fd, " RTP dynamic payload types: %u-%u\n",
572  }
573 
574  ast_cli(a->fd, "\n* Subsystems\n");
575  ast_cli(a->fd, " -------------\n");
576  ast_cli(a->fd, " Manager (AMI): %s\n", ast_manager_check_enabled() ? "Enabled" : "Disabled");
577  ast_cli(a->fd, " Web Manager (AMI/HTTP): %s\n", ast_webmanager_check_enabled() ? "Enabled" : "Disabled");
578  ast_cli(a->fd, " Call data records: %s\n", ast_cdr_is_enabled() ? "Enabled" : "Disabled");
579  ast_cli(a->fd, " Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
580 
581  /*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
582 
583  ast_cli(a->fd, "\n* Directories\n");
584  ast_cli(a->fd, " -------------\n");
585  ast_cli(a->fd, " Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
586  ast_cli(a->fd, " Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
587  ast_cli(a->fd, " Module directory: %s\n", ast_config_AST_MODULE_DIR);
588  ast_cli(a->fd, " Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
589  ast_cli(a->fd, " Log directory: %s\n", ast_config_AST_LOG_DIR);
590  ast_cli(a->fd, " Run/Sockets directory: %s\n", ast_config_AST_RUN_DIR);
591  ast_cli(a->fd, " PID file: %s\n", ast_config_AST_PID);
592  ast_cli(a->fd, " VarLib directory: %s\n", ast_config_AST_VAR_DIR);
593  ast_cli(a->fd, " Data directory: %s\n", ast_config_AST_DATA_DIR);
594  ast_cli(a->fd, " ASTDB: %s\n", ast_config_AST_DB);
595  ast_cli(a->fd, " IAX2 Keys directory: %s\n", ast_config_AST_KEY_DIR);
596  ast_cli(a->fd, " AGI Scripts directory: %s\n", ast_config_AST_AGI_DIR);
597  ast_cli(a->fd, "\n\n");
598  return CLI_SUCCESS;
599 }
600 
601 static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
602 {
603  int count = 0;
604  struct thread_list_t *cur;
605  switch (cmd) {
606  case CLI_INIT:
607  e->command = "core show threads";
608  e->usage =
609  "Usage: core show threads\n"
610  " List threads currently active in the system.\n";
611  return NULL;
612  case CLI_GENERATE:
613  return NULL;
614  }
615 
617  AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
618  ast_cli(a->fd, "%p %d %s\n", (void *)cur->id, cur->lwp, cur->name);
619  count++;
620  }
622  ast_cli(a->fd, "%d threads listed.\n", count);
623  return CLI_SUCCESS;
624 }
625 
626 #if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
627 /*
628  * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
629  * to be based on the new swapctl(2) system call.
630  */
631 static int swapmode(int *used, int *total)
632 {
633  struct swapent *swdev;
634  int nswap, rnswap, i;
635 
636  nswap = swapctl(SWAP_NSWAP, 0, 0);
637  if (nswap == 0)
638  return 0;
639 
640  swdev = ast_calloc(nswap, sizeof(*swdev));
641  if (swdev == NULL)
642  return 0;
643 
644  rnswap = swapctl(SWAP_STATS, swdev, nswap);
645  if (rnswap == -1) {
646  ast_free(swdev);
647  return 0;
648  }
649 
650  /* if rnswap != nswap, then what? */
651 
652  /* Total things up */
653  *total = *used = 0;
654  for (i = 0; i < nswap; i++) {
655  if (swdev[i].se_flags & SWF_ENABLE) {
656  *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
657  *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
658  }
659  }
660  ast_free(swdev);
661  return 1;
662 }
663 #endif
664 
665 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
666 /*! \brief Give an overview of system statistics */
667 static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
668 {
669  uint64_t physmem, freeram;
670 #if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
671  int totalswap = 0;
672  uint64_t freeswap = 0;
673 #endif
674  int nprocs = 0;
675  long uptime = 0;
676 #if defined(HAVE_SYSINFO)
677  struct sysinfo sys_info;
678 #elif defined(HAVE_SYSCTL)
679  static int pageshift;
680  struct vmtotal vmtotal;
681  struct timeval boottime;
682  time_t now;
683  int mib[2], pagesize;
684 #if defined(HAVE_SWAPCTL)
685  int usedswap = 0;
686 #endif
687  size_t len;
688 #endif
689 
690  switch (cmd) {
691  case CLI_INIT:
692  e->command = "core show sysinfo";
693  e->usage =
694  "Usage: core show sysinfo\n"
695  " List current system information.\n";
696  return NULL;
697  case CLI_GENERATE:
698  return NULL;
699  }
700 
701 #if defined(HAVE_SYSINFO)
702  sysinfo(&sys_info);
703  uptime = sys_info.uptime / 3600;
704  physmem = sys_info.totalram * sys_info.mem_unit;
705  freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
706  totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
707  freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
708  nprocs = sys_info.procs;
709 #elif defined(HAVE_SYSCTL)
710  /* calculate the uptime by looking at boottime */
711  time(&now);
712  mib[0] = CTL_KERN;
713  mib[1] = KERN_BOOTTIME;
714  len = sizeof(boottime);
715  if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
716  uptime = now - boottime.tv_sec;
717  }
718  uptime = uptime/3600;
719  /* grab total physical memory */
720  mib[0] = CTL_HW;
721 #if defined(HW_PHYSMEM64)
722  mib[1] = HW_PHYSMEM64;
723 #else
724  mib[1] = HW_PHYSMEM;
725 #endif
726  len = sizeof(physmem);
727  sysctl(mib, 2, &physmem, &len, NULL, 0);
728 
729  pagesize = getpagesize();
730  pageshift = 0;
731  while (pagesize > 1) {
732  pageshift++;
733  pagesize >>= 1;
734  }
735 
736  /* we only need the amount of log(2)1024 for our conversion */
737  pageshift -= 10;
738 
739  /* grab vm totals */
740  mib[0] = CTL_VM;
741  mib[1] = VM_METER;
742  len = sizeof(vmtotal);
743  sysctl(mib, 2, &vmtotal, &len, NULL, 0);
744  freeram = (vmtotal.t_free << pageshift);
745  /* generate swap usage and totals */
746 #if defined(HAVE_SWAPCTL)
747  swapmode(&usedswap, &totalswap);
748  freeswap = (totalswap - usedswap);
749 #endif
750  /* grab number of processes */
751 #if defined(__OpenBSD__)
752  mib[0] = CTL_KERN;
753  mib[1] = KERN_NPROCS;
754  len = sizeof(nprocs);
755  sysctl(mib, 2, &nprocs, &len, NULL, 0);
756 #endif
757 #endif
758 
759  ast_cli(a->fd, "\nSystem Statistics\n");
760  ast_cli(a->fd, "-----------------\n");
761  ast_cli(a->fd, " System Uptime: %ld hours\n", uptime);
762  ast_cli(a->fd, " Total RAM: %" PRIu64 " KiB\n", physmem / 1024);
763  ast_cli(a->fd, " Free RAM: %" PRIu64 " KiB\n", freeram);
764 #if defined(HAVE_SYSINFO)
765  ast_cli(a->fd, " Buffer RAM: %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
766 #endif
767 #if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
768  ast_cli(a->fd, " Total Swap Space: %d KiB\n", totalswap);
769  ast_cli(a->fd, " Free Swap Space: %" PRIu64 " KiB\n\n", freeswap);
770 #endif
771  ast_cli(a->fd, " Number of Processes: %d \n\n", nprocs);
772  return CLI_SUCCESS;
773 }
774 #endif
775 
777  const char *name;
778  uint64_t scale; /* if non-zero, values are scaled by this */
779  int64_t mark;
780  int64_t value;
781  int64_t events;
782 };
783 
784 struct profile_data {
785  int entries;
786  int max_size;
787  struct profile_entry e[0];
788 };
789 
790 static struct profile_data *prof_data;
791 #endif /* ! LOW_MEMORY */
792 
793 /*! \brief allocates a counter with a given name and scale.
794  * \return Returns the identifier of the counter.
795  */
796 int ast_add_profile(const char *name, uint64_t scale)
797 {
798 #if !defined(LOW_MEMORY)
799  int l = sizeof(struct profile_data);
800  int n = 10; /* default entries */
801 
802  if (prof_data == NULL) {
803  prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
804  if (prof_data == NULL)
805  return -1;
806  prof_data->entries = 0;
807  prof_data->max_size = n;
808  }
809  if (prof_data->entries >= prof_data->max_size) {
810  void *p;
811  n = prof_data->max_size + 20;
812  p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
813  if (p == NULL)
814  return -1;
815  prof_data = p;
816  prof_data->max_size = n;
817  }
818  n = prof_data->entries++;
819  prof_data->e[n].name = ast_strdup(name);
820  prof_data->e[n].value = 0;
821  prof_data->e[n].events = 0;
822  prof_data->e[n].mark = 0;
823  prof_data->e[n].scale = scale;
824  return n;
825 #else /* if defined(LOW_MEMORY) */
826  return 0;
827 #endif
828 }
829 
830 int64_t ast_profile(int i, int64_t delta)
831 {
832 #if !defined(LOW_MEMORY)
833  if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
834  return 0;
835  if (prof_data->e[i].scale > 1)
836  delta /= prof_data->e[i].scale;
837  prof_data->e[i].value += delta;
838  prof_data->e[i].events++;
839  return prof_data->e[i].value;
840 #else /* if defined(LOW_MEMORY) */
841  return 0;
842 #endif
843 }
844 
845 #if !defined(LOW_MEMORY)
846 /* The RDTSC instruction was introduced on the Pentium processor and is not
847  * implemented on certain clones, like the Cyrix 586. Hence, the previous
848  * expectation of __i386__ was in error. */
849 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(__NetBSD__) || defined(linux))
850 #if defined(__FreeBSD__)
851 #include <machine/cpufunc.h>
852 #elif defined(__NetBSD__) || defined(linux)
853 static __inline uint64_t
854 rdtsc(void)
855 {
856  uint64_t rv;
857 
858  __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
859  return (rv);
860 }
861 #endif
862 #else /* supply a dummy function on other platforms */
863 static __inline uint64_t
864 rdtsc(void)
865 {
866  return 0;
867 }
868 #endif
869 #endif /* ! LOW_MEMORY */
870 
871 int64_t ast_mark(int i, int startstop)
872 {
873 #if !defined(LOW_MEMORY)
874  if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
875  return 0;
876  if (startstop == 1)
877  prof_data->e[i].mark = rdtsc();
878  else {
879  prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
880  if (prof_data->e[i].scale > 1)
881  prof_data->e[i].mark /= prof_data->e[i].scale;
882  prof_data->e[i].value += prof_data->e[i].mark;
883  prof_data->e[i].events++;
884  }
885  return prof_data->e[i].mark;
886 #else /* if defined(LOW_MEMORY) */
887  return 0;
888 #endif
889 }
890 
891 #if !defined(LOW_MEMORY)
892 #define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
893  max = prof_data->entries;\
894  if (a->argc > 3) { /* specific entries */ \
895  if (isdigit(a->argv[3][0])) { \
896  min = atoi(a->argv[3]); \
897  if (a->argc == 5 && strcmp(a->argv[4], "-")) \
898  max = atoi(a->argv[4]); \
899  } else \
900  search = a->argv[3]; \
901  } \
902  if (max > prof_data->entries) \
903  max = prof_data->entries;
904 
905 static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
906 {
907  int i, min, max;
908  const char *search = NULL;
909  switch (cmd) {
910  case CLI_INIT:
911  e->command = "core show profile";
912  e->usage = "Usage: core show profile\n"
913  " show profile information";
914  return NULL;
915  case CLI_GENERATE:
916  return NULL;
917  }
918 
919  if (prof_data == NULL)
920  return 0;
921 
923  ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
925  ast_cli(a->fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
926  "Value", "Average", "Name");
927  for (i = min; i < max; i++) {
928  struct profile_entry *entry = &prof_data->e[i];
929  if (!search || strstr(entry->name, search))
930  ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
931  i,
932  (long)entry->scale,
933  (long)entry->events, (long long)entry->value,
934  (long long)(entry->events ? entry->value / entry->events : entry->value),
935  entry->name);
936  }
937  return CLI_SUCCESS;
938 }
939 
940 static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
941 {
942  int i, min, max;
943  const char *search = NULL;
944  switch (cmd) {
945  case CLI_INIT:
946  e->command = "core clear profile";
947  e->usage = "Usage: core clear profile\n"
948  " clear profile information";
949  return NULL;
950  case CLI_GENERATE:
951  return NULL;
952  }
953 
954  if (prof_data == NULL)
955  return 0;
956 
958  for (i= min; i < max; i++) {
959  if (!search || strstr(prof_data->e[i].name, search)) {
960  prof_data->e[i].value = 0;
961  prof_data->e[i].events = 0;
962  }
963  }
964  return CLI_SUCCESS;
965 }
966 #undef DEFINE_PROFILE_MIN_MAX_VALUES
967 
968 #endif /* ! LOW_MEMORY */
969 
970 int ast_pbx_uuid_get(char *pbx_uuid, int length)
971 {
972  return ast_db_get("pbx", "UUID", pbx_uuid, length);
973 }
974 
975 static void publish_fully_booted(void)
976 {
977  struct ast_json *json_object;
978  int uptime = 0;
979  int lastreloaded = 0;
980  struct timeval tmp;
981  struct timeval curtime = ast_tvnow();
982 
983  if (ast_startuptime.tv_sec) {
984  tmp = ast_tvsub(curtime, ast_startuptime);
985  uptime = (int) tmp.tv_sec;
986  }
987 
988  if (ast_lastreloadtime.tv_sec) {
989  tmp = ast_tvsub(curtime, ast_lastreloadtime);
990  lastreloaded = (int) tmp.tv_sec;
991  }
992 
993  json_object = ast_json_pack("{s: s, s: i, s: i}",
994  "Status", "Fully Booted",
995  "Uptime", uptime,
996  "LastReload", lastreloaded);
997  ast_manager_publish_event("FullyBooted", EVENT_FLAG_SYSTEM, json_object);
998  ast_json_unref(json_object);
999 }
1000 
1001 static void ast_run_atexits(int run_cleanups)
1002 {
1003  struct ast_atexit *ae;
1004 
1006  while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
1007  if (ae->func && (!ae->is_cleanup || run_cleanups)) {
1008  ae->func();
1009  }
1010  ast_free(ae);
1011  }
1013 }
1014 
1015 static void __ast_unregister_atexit(void (*func)(void))
1016 {
1017  struct ast_atexit *ae;
1018 
1020  if (ae->func == func) {
1022  ast_free(ae);
1023  break;
1024  }
1025  }
1027 }
1028 
1029 static int register_atexit(void (*func)(void), int is_cleanup)
1030 {
1031  struct ast_atexit *ae;
1032 
1033  ae = ast_calloc(1, sizeof(*ae));
1034  if (!ae) {
1035  return -1;
1036  }
1037  ae->func = func;
1038  ae->is_cleanup = is_cleanup;
1039 
1044 
1045  return 0;
1046 }
1047 
1048 int ast_register_atexit(void (*func)(void))
1049 {
1050  return register_atexit(func, 0);
1051 }
1052 
1053 int ast_register_cleanup(void (*func)(void))
1054 {
1055  return register_atexit(func, 1);
1056 }
1057 
1058 void ast_unregister_atexit(void (*func)(void))
1059 {
1063 }
1064 
1065 /* Sending commands from consoles back to the daemon requires a terminating NULL */
1066 static int fdsend(int fd, const char *s)
1067 {
1068  return write(fd, s, strlen(s) + 1);
1069 }
1070 
1071 /* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
1072 static int fdprint(int fd, const char *s)
1073 {
1074  return write(fd, s, strlen(s));
1075 }
1076 
1077 /*! \brief NULL handler so we can collect the child exit status */
1078 static void _null_sig_handler(int sig)
1079 {
1080 }
1081 
1082 static struct sigaction null_sig_handler = {
1083  .sa_handler = _null_sig_handler,
1084  .sa_flags = SA_RESTART,
1085 };
1086 
1087 static struct sigaction ignore_sig_handler = {
1088  .sa_handler = SIG_IGN,
1089 };
1090 
1092 /*! \brief Keep track of how many threads are currently trying to wait*() on
1093  * a child process
1094  */
1095 static unsigned int safe_system_level = 0;
1096 static struct sigaction safe_system_prev_handler;
1097 
1099 {
1100  unsigned int level;
1101 
1103  level = safe_system_level++;
1104 
1105  /* only replace the handler if it has not already been done */
1106  if (level == 0) {
1107  sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1108  }
1109 
1111 }
1112 
1114 {
1115  unsigned int level;
1116 
1118  level = --safe_system_level;
1119 
1120  /* only restore the handler if we are the last one */
1121  if (level == 0) {
1122  sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1123  }
1124 
1126 }
1127 
1128 /*! \brief fork and perform other preparations for spawning applications */
1129 static pid_t safe_exec_prep(int dualfork)
1130 {
1131  pid_t pid;
1132 
1133 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1135 
1136 #ifdef HAVE_WORKING_FORK
1137  pid = fork();
1138 #else
1139  pid = vfork();
1140 #endif
1141 
1142  if (pid == 0) {
1143 #ifdef HAVE_CAP
1144  cap_set_proc(child_cap);
1145 #endif
1146 #ifdef HAVE_WORKING_FORK
1147  if (ast_opt_high_priority) {
1148  ast_set_priority(0);
1149  }
1150  /* Close file descriptors and launch system command */
1151  ast_close_fds_above_n(STDERR_FILENO);
1152 #endif
1153  if (dualfork) {
1154 #ifdef HAVE_WORKING_FORK
1155  pid = fork();
1156 #else
1157  pid = vfork();
1158 #endif
1159  if (pid < 0) {
1160  /* Second fork failed. */
1161  /* No logger available. */
1162  _exit(1);
1163  }
1164 
1165  if (pid > 0) {
1166  /* This is the first fork, exit so the reaper finishes right away. */
1167  _exit(0);
1168  }
1169 
1170  /* This is the second fork. The first fork will exit immediately so
1171  * Asterisk doesn't have to wait for completion.
1172  * ast_safe_system("cmd &") would run in the background, but the '&'
1173  * cannot be added with ast_safe_execvp, so we have to double fork.
1174  */
1175  }
1176  }
1177 
1178  if (pid < 0) {
1179  ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
1180  }
1181 #else
1182  ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(ENOTSUP));
1183  pid = -1;
1184 #endif
1185 
1186  return pid;
1187 }
1188 
1189 /*! \brief wait for spawned application to complete and unreplace sigchld */
1190 static int safe_exec_wait(pid_t pid)
1191 {
1192  int res = -1;
1193 
1194 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1195  if (pid > 0) {
1196  for (;;) {
1197  int status;
1198 
1199  res = waitpid(pid, &status, 0);
1200  if (res > -1) {
1201  res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1202  break;
1203  }
1204  if (errno != EINTR) {
1205  break;
1206  }
1207  }
1208  }
1209 
1211 #endif
1212 
1213  return res;
1214 }
1215 
1216 int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
1217 {
1218  pid_t pid = safe_exec_prep(dualfork);
1219 
1220  if (pid == 0) {
1221  execvp(file, argv);
1222  _exit(1);
1223  /* noreturn from _exit */
1224  }
1225 
1226  return safe_exec_wait(pid);
1227 }
1228 
1229 int ast_safe_system(const char *s)
1230 {
1231  pid_t pid = safe_exec_prep(0);
1232 
1233  if (pid == 0) {
1234  execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
1235  _exit(1);
1236  /* noreturn from _exit */
1237  }
1238 
1239  return safe_exec_wait(pid);
1240 }
1241 
1242 /*!
1243  * \brief enable or disable a logging level to a specified console
1244  */
1245 void ast_console_toggle_loglevel(int fd, int level, int state)
1246 {
1247  int x;
1248 
1249  if (level >= NUMLOGLEVELS) {
1250  level = NUMLOGLEVELS - 1;
1251  }
1252 
1253  for (x = 0;x < AST_MAX_CONNECTS; x++) {
1254  if (fd == consoles[x].fd) {
1255  /*
1256  * Since the logging occurs when levels are false, set to
1257  * flipped iinput because this function accepts 0 as off and 1 as on
1258  */
1259  consoles[x].levels[level] = state ? 0 : 1;
1260  return;
1261  }
1262  }
1263 }
1264 
1265 /*!
1266  * \brief mute or unmute a console from logging
1267  */
1268 void ast_console_toggle_mute(int fd, int silent)
1269 {
1270  int x;
1271  for (x = 0;x < AST_MAX_CONNECTS; x++) {
1272  if (fd == consoles[x].fd) {
1273  if (consoles[x].mute) {
1274  consoles[x].mute = 0;
1275  if (!silent)
1276  ast_cli(fd, "Console is not muted anymore.\n");
1277  } else {
1278  consoles[x].mute = 1;
1279  if (!silent)
1280  ast_cli(fd, "Console is muted.\n");
1281  }
1282  return;
1283  }
1284  }
1285  ast_cli(fd, "Couldn't find remote console.\n");
1286 }
1287 
1288 /*!
1289  * \brief log the string to all attached network console clients
1290  */
1291 static void ast_network_puts_mutable(const char *string, int level, int sublevel)
1292 {
1293  int x;
1294 
1295  for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1296  if (consoles[x].fd < 0
1297  || consoles[x].mute
1298  || consoles[x].levels[level]
1299  || (level == __LOG_VERBOSE && consoles[x].option_verbose < sublevel)) {
1300  continue;
1301  }
1302  fdprint(consoles[x].p[1], string);
1303  }
1304 }
1305 
1306 /*!
1307  * \brief log the string to the root console, and all attached
1308  * network console clients
1309  */
1310 void ast_console_puts_mutable(const char *string, int level)
1311 {
1312  ast_console_puts_mutable_full(string, level, 0);
1313 }
1314 
1315 static int console_print(const char *s);
1316 
1317 void ast_console_puts_mutable_full(const char *message, int level, int sublevel)
1318 {
1319  /* Send to the root console */
1321 
1322  /* Wake up a poll()ing console */
1324  pthread_kill(consolethread, SIGURG);
1325  }
1326 
1327  /* Send to any network console clients */
1328  ast_network_puts_mutable(message, level, sublevel);
1329 }
1330 
1331 /*!
1332  * \brief write the string to all attached console clients
1333  */
1334 static void ast_network_puts(const char *string)
1335 {
1336  int x;
1337 
1338  for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1339  if (consoles[x].fd < 0) {
1340  continue;
1341  }
1342  fdprint(consoles[x].p[1], string);
1343  }
1344 }
1345 
1346 /*!
1347  * \brief write the string to the root console, and all attached
1348  * network console clients
1349  */
1350 void ast_console_puts(const char *string)
1351 {
1352  /* Send to the root console */
1353  fputs(string, stdout);
1354  fflush(stdout);
1355 
1356  /* Send to any network console clients */
1357  ast_network_puts(string);
1358 }
1359 
1360 static pthread_t lthread;
1361 
1362 /*!
1363  * \brief read() function supporting the reception of user credentials.
1364  *
1365  * \param fd Socket file descriptor.
1366  * \param buffer Receive buffer.
1367  * \param size 'buffer' size.
1368  * \param con Console structure to set received credentials
1369  * \retval -1 on error
1370  * \retval the number of bytes received on success.
1371  */
1372 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1373 {
1374 #if defined(SO_PEERCRED)
1375 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1376 #define HAVE_STRUCT_UCRED_UID
1377  struct sockpeercred cred;
1378 #else
1379  struct ucred cred;
1380 #endif
1381  socklen_t len = sizeof(cred);
1382 #endif
1383 #if defined(HAVE_GETPEEREID)
1384  uid_t uid;
1385  gid_t gid;
1386 #else
1387  int uid, gid;
1388 #endif
1389  int result;
1390 
1391  result = read(fd, buffer, size);
1392  if (result < 0) {
1393  return result;
1394  }
1395 
1396 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1397  if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1398  return result;
1399  }
1400 #if defined(HAVE_STRUCT_UCRED_UID)
1401  uid = cred.uid;
1402  gid = cred.gid;
1403 #else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1404  uid = cred.cr_uid;
1405  gid = cred.cr_gid;
1406 #endif /* defined(HAVE_STRUCT_UCRED_UID) */
1407 
1408 #elif defined(HAVE_GETPEEREID)
1409  if (getpeereid(fd, &uid, &gid)) {
1410  return result;
1411  }
1412 #else
1413  return result;
1414 #endif
1415  con->uid = uid;
1416  con->gid = gid;
1417 
1418  return result;
1419 }
1420 
1421 /* This is the thread running the remote console on the main process. */
1422 static void *netconsole(void *vconsole)
1423 {
1424  struct console *con = vconsole;
1425  char hostname[MAXHOSTNAMELEN] = "";
1426  char inbuf[512];
1427  char outbuf[512];
1428  const char * const end_buf = inbuf + sizeof(inbuf);
1429  char *start_read = inbuf;
1430  int res;
1431  struct pollfd fds[2];
1432 
1433  if (gethostname(hostname, sizeof(hostname)-1))
1434  ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1435  snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1436  fdprint(con->fd, outbuf);
1438  for (;;) {
1439  fds[0].fd = con->fd;
1440  fds[0].events = POLLIN;
1441  fds[0].revents = 0;
1442  fds[1].fd = con->p[0];
1443  fds[1].events = POLLIN;
1444  fds[1].revents = 0;
1445 
1446  res = ast_poll(fds, 2, -1);
1447  if (res < 0) {
1448  if (errno != EINTR)
1449  ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1450  continue;
1451  }
1452  if (fds[0].revents) {
1453  int cmds_read, bytes_read;
1454  if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) {
1455  break;
1456  }
1457  /* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */
1458  if (strncmp(inbuf, "cli quit after ", 15) == 0) {
1459  ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15);
1460  break;
1461  }
1462  /* ast_cli_command_multiple_full will only process individual commands terminated by a
1463  * NULL and not trailing partial commands. */
1464  if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) {
1465  /* No commands were read. We either have a short read on the first command
1466  * with space left, or a command that is too long */
1467  if (start_read + bytes_read < end_buf) {
1468  start_read += bytes_read;
1469  } else {
1470  ast_log(LOG_ERROR, "Command too long! Skipping\n");
1471  start_read = inbuf;
1472  }
1473  continue;
1474  }
1475  if (start_read[bytes_read - 1] == '\0') {
1476  /* The read ended on a command boundary, start reading again at the head of inbuf */
1477  start_read = inbuf;
1478  continue;
1479  }
1480  /* If we get this far, we have left over characters that have not been processed.
1481  * Advance to the character after the last command read by ast_cli_command_multiple_full.
1482  * We are guaranteed to have at least cmds_read NULLs */
1483  while (cmds_read-- && (start_read = strchr(start_read, '\0'))) {
1484  start_read++;
1485  }
1486  memmove(inbuf, start_read, end_buf - start_read);
1487  start_read = end_buf - start_read + inbuf;
1488  }
1489  if (fds[1].revents) {
1490  res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con);
1491  if (res < 1) {
1492  ast_log(LOG_ERROR, "read returned %d\n", res);
1493  break;
1494  }
1495  res = write(con->fd, outbuf, res);
1496  if (res < 1)
1497  break;
1498  }
1499  }
1501  if (!ast_opt_hide_connect) {
1502  ast_verb(3, "Remote UNIX connection disconnected\n");
1503  }
1504  close(con->fd);
1505  close(con->p[0]);
1506  close(con->p[1]);
1507  con->fd = -1;
1508 
1509  return NULL;
1510 }
1511 
1512 static void *listener(void *unused)
1513 {
1514  struct sockaddr_un sunaddr;
1515  int s;
1516  socklen_t len;
1517  int x;
1518  int poll_result;
1519  struct pollfd fds[1];
1520 
1521  for (;;) {
1522  if (ast_socket < 0) {
1523  return NULL;
1524  }
1525  fds[0].fd = ast_socket;
1526  fds[0].events = POLLIN;
1527  poll_result = ast_poll(fds, 1, -1);
1528  pthread_testcancel();
1529  if (poll_result < 0) {
1530  if (errno != EINTR) {
1531  ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1532  }
1533  continue;
1534  }
1535  len = sizeof(sunaddr);
1536  s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1537  if (s < 0) {
1538  if (errno != EINTR)
1539  ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1540  } else {
1541 #if defined(SO_PASSCRED)
1542  int sckopt = 1;
1543  /* turn on socket credentials passing. */
1544  if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1545  ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1546  close(s);
1547  } else
1548 #endif
1549  {
1550  for (x = 0; x < AST_MAX_CONNECTS; x++) {
1551  if (consoles[x].fd >= 0) {
1552  continue;
1553  }
1554  if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1555  ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1556  fdprint(s, "Server failed to create pipe\n");
1557  close(s);
1558  break;
1559  }
1560  ast_fd_set_flags(consoles[x].p[1], O_NONBLOCK);
1561  consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1562  /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1563  to know if the user didn't send the credentials. */
1564  consoles[x].uid = -2;
1565  consoles[x].gid = -2;
1566  /* Server default of remote console verbosity level is OFF. */
1567  consoles[x].option_verbose = 0;
1568  consoles[x].fd = s;
1570  consoles[x].fd = -1;
1571  ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1572  close(consoles[x].p[0]);
1573  close(consoles[x].p[1]);
1574  fdprint(s, "Server failed to spawn thread\n");
1575  close(s);
1576  }
1577  break;
1578  }
1579  if (x >= AST_MAX_CONNECTS) {
1580  fdprint(s, "No more connections allowed\n");
1581  ast_log(LOG_WARNING, "No more connections allowed\n");
1582  close(s);
1583  } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1584  ast_verb(3, "Remote UNIX connection\n");
1585  }
1586  }
1587  }
1588  }
1589  return NULL;
1590 }
1591 
1592 static int ast_makesocket(void)
1593 {
1594  struct sockaddr_un sunaddr;
1595  int res;
1596  int x;
1597  uid_t uid = -1;
1598  gid_t gid = -1;
1599 
1600  for (x = 0; x < AST_MAX_CONNECTS; x++) {
1601  consoles[x].fd = -1;
1602  }
1603 
1604  if (ast_socket_is_sd) {
1606 
1607  goto start_lthread;
1608  }
1609 
1610  unlink(ast_config_AST_SOCKET);
1611  ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1612  if (ast_socket < 0) {
1613  ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1614  return -1;
1615  }
1616  memset(&sunaddr, 0, sizeof(sunaddr));
1617  sunaddr.sun_family = AF_LOCAL;
1618  ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1619  res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1620  if (res) {
1621  ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1622  close(ast_socket);
1623  ast_socket = -1;
1624  return -1;
1625  }
1626  res = listen(ast_socket, 2);
1627  if (res < 0) {
1628  ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1629  close(ast_socket);
1630  ast_socket = -1;
1631  return -1;
1632  }
1633 
1634 start_lthread:
1636  ast_log(LOG_WARNING, "Unable to create listener thread.\n");
1637  close(ast_socket);
1638  return -1;
1639  }
1640 
1641  if (ast_socket_is_sd) {
1642  /* owner/group/permissions are set by systemd, we might not even have access
1643  * to socket file so leave it alone */
1644  return 0;
1645  }
1646 
1648  struct passwd *pw;
1649  if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1650  ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1651  else
1652  uid = pw->pw_uid;
1653  }
1654 
1656  struct group *grp;
1657  if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1658  ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1659  else
1660  gid = grp->gr_gid;
1661  }
1662 
1663  if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1664  ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1665 
1667  unsigned int p1;
1668  mode_t p;
1669  sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1670  p = p1;
1671  if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1672  ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1673  }
1674 
1675  return 0;
1676 }
1677 
1678 static int ast_tryconnect(void)
1679 {
1680  struct sockaddr_un sunaddr;
1681  int res;
1682  ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1683  if (ast_consock < 0) {
1684  fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
1685  return 0;
1686  }
1687  memset(&sunaddr, 0, sizeof(sunaddr));
1688  sunaddr.sun_family = AF_LOCAL;
1689  ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1690  res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1691  if (res) {
1692  close(ast_consock);
1693  ast_consock = -1;
1694  return 0;
1695  } else
1696  return 1;
1697 }
1698 
1699 /*! \brief Urgent handler
1700  *
1701  * Called by soft_hangup to interrupt the poll, read, or other
1702  * system call. We don't actually need to do anything though.
1703  * Remember: Cannot EVER ast_log from within a signal handler
1704  */
1705 static void _urg_handler(int num)
1706 {
1707  return;
1708 }
1709 
1710 static struct sigaction urg_handler = {
1711  .sa_handler = _urg_handler,
1712 };
1713 
1714 static void _hup_handler(int num)
1715 {
1716  int save_errno = errno;
1717 
1718  if (restartnow) {
1719  if (el) {
1720  el_end(el);
1721  }
1722  execvp(_argv[0], _argv);
1723  }
1724 
1725  printf("Received HUP signal -- Reloading configs\n");
1726  sig_flags.need_reload = 1;
1728  fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1729  }
1730  errno = save_errno;
1731 }
1732 
1733 static struct sigaction hup_handler = {
1734  .sa_handler = _hup_handler,
1735  .sa_flags = SA_RESTART,
1736 };
1737 
1738 static void _child_handler(int sig)
1739 {
1740  /* Must not ever ast_log or ast_verbose within signal handler */
1741  int n, status, save_errno = errno;
1742 
1743  /*
1744  * Reap all dead children -- not just one
1745  */
1746  for (n = 0; waitpid(-1, &status, WNOHANG) > 0; n++)
1747  ;
1748  if (n == 0 && option_debug)
1749  printf("Huh? Child handler, but nobody there?\n");
1750  errno = save_errno;
1751 }
1752 
1753 static struct sigaction child_handler = {
1754  .sa_handler = _child_handler,
1755  .sa_flags = SA_RESTART,
1756 };
1757 
1758 /*! \brief Set an X-term or screen title */
1759 static void set_title(char *text)
1760 {
1761  if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1762  fprintf(stdout, "\033]2;%s\007", text);
1763 }
1764 
1765 static void set_icon(char *text)
1766 {
1767  if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1768  fprintf(stdout, "\033]1;%s\007", text);
1769 }
1770 
1771 /*! \brief Check whether we were set to high(er) priority. */
1772 static int has_priority(void)
1773 {
1774  /* Neither of these calls should fail with these arguments. */
1775 #ifdef __linux__
1776  /* For SCHED_OTHER, SCHED_BATCH and SCHED_IDLE, this will return
1777  * 0. For the realtime priorities SCHED_RR and SCHED_FIFO, it
1778  * will return something >= 1. */
1779  return sched_getscheduler(0);
1780 #else
1781  /* getpriority() can return a value in -20..19 (or even -INF..20)
1782  * where negative numbers are high priority. We don't bother
1783  * checking errno. If the query fails and it returns -1, we'll
1784  * assume that we're running at high prio; a safe assumption
1785  * that will enable the resource starvation monitor (canary)
1786  * just in case. */
1787  return (getpriority(PRIO_PROCESS, 0) < 0);
1788 #endif
1789 }
1790 
1791 /*! \brief Set priority on all known threads. */
1792 static int set_priority_all(int pri)
1793 {
1794 #if !defined(__linux__)
1795  /* The non-linux version updates the entire process prio. */
1796  return ast_set_priority(pri);
1797 #elif defined(LOW_MEMORY)
1798  ast_log(LOG_WARNING, "Unable to enumerate all threads to update priority\n");
1799  return ast_set_priority(pri);
1800 #else
1801  struct thread_list_t *cur;
1802  struct sched_param sched;
1803  char const *policy_str;
1804  int policy;
1805 
1806  memset(&sched, 0, sizeof(sched));
1807  if (pri) {
1808  policy = SCHED_RR;
1809  policy_str = "realtime";
1810  sched.sched_priority = 10;
1811  } else {
1812  policy = SCHED_OTHER;
1813  policy_str = "regular";
1814  sched.sched_priority = 0;
1815  }
1816  if (sched_setscheduler(getpid(), policy, &sched)) {
1817  ast_log(LOG_WARNING, "Unable to set %s thread priority on main thread\n", policy_str);
1818  return -1;
1819  }
1820  ast_verb(1, "Setting %s thread priority on all threads\n", policy_str);
1822  AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
1823  /* Don't care about the return value. It should work. */
1824  sched_setscheduler(cur->lwp, policy, &sched);
1825  }
1827  return 0;
1828 #endif
1829 }
1830 
1831 /*! \brief We set ourselves to a high priority, that we might pre-empt
1832  * everything else. If your PBX has heavy activity on it, this is a
1833  * good thing.
1834  */
1835 int ast_set_priority(int pri)
1836 {
1837  struct sched_param sched;
1838  memset(&sched, 0, sizeof(sched));
1839 #ifdef __linux__
1840  if (pri) {
1841  sched.sched_priority = 10;
1842  if (sched_setscheduler(0, SCHED_RR, &sched)) {
1843  return -1;
1844  }
1845  } else {
1846  sched.sched_priority = 0;
1847  /* According to the manpage, these parameters can never fail. */
1848  sched_setscheduler(0, SCHED_OTHER, &sched);
1849  }
1850 #else
1851  if (pri) {
1852  if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1853  ast_log(LOG_WARNING, "Unable to set high priority\n");
1854  return -1;
1855  } else
1856  ast_verb(1, "Set to high priority\n");
1857  } else {
1858  /* According to the manpage, these parameters can never fail. */
1859  setpriority(PRIO_PROCESS, 0, 0);
1860  }
1861 #endif
1862  return 0;
1863 }
1864 
1866 {
1868 }
1869 
1871 {
1872  return shutdown_pending;
1873 }
1874 
1876 {
1877  int shutdown_aborted = 0;
1878 
1880  if (shuttingdown >= SHUTDOWN_FAST) {
1882  shutdown_pending = 0;
1883  shutdown_aborted = 1;
1884  }
1886  return shutdown_aborted;
1887 }
1888 
1889 /*!
1890  * \internal
1891  * \brief Initiate system shutdown -- prevents new channels from being allocated.
1892  */
1893 static void ast_begin_shutdown(void)
1894 {
1897  shutdown_pending = 1;
1898  }
1900 }
1901 
1902 static int can_safely_quit(shutdown_nice_t niceness, int restart);
1903 static void really_quit(int num, shutdown_nice_t niceness, int restart);
1904 
1905 static void quit_handler(int num, shutdown_nice_t niceness, int restart)
1906 {
1907  if (can_safely_quit(niceness, restart)) {
1908  really_quit(num, niceness, restart);
1909  /* No one gets here. */
1910  }
1911  /* It wasn't our time. */
1912 }
1913 
1914 #define SHUTDOWN_TIMEOUT 15 /* Seconds */
1915 
1916 /*!
1917  * \internal
1918  * \brief Wait for all channels to die, a timeout, or shutdown cancelled.
1919  * \since 13.3.0
1920  *
1921  * \param niceness Shutdown niceness in effect
1922  * \param seconds Number of seconds to wait or less than zero if indefinitely.
1923  *
1924  * \retval zero if waiting wasn't necessary. We were idle.
1925  * \retval non-zero if we had to wait.
1926  */
1927 static int wait_for_channels_to_die(shutdown_nice_t niceness, int seconds)
1928 {
1929  time_t start;
1930  time_t now;
1931  int waited = 0;
1932 
1933  time(&start);
1934  for (;;) {
1935  if (!ast_undestroyed_channels() || shuttingdown != niceness) {
1936  break;
1937  }
1938  if (seconds < 0) {
1939  /* No timeout so just poll every second */
1940  sleep(1);
1941  } else {
1942  time(&now);
1943 
1944  /* Wait up to the given seconds for all channels to go away */
1945  if (seconds < (now - start)) {
1946  break;
1947  }
1948 
1949  /* Sleep 1/10 of a second */
1950  usleep(100000);
1951  }
1952  waited = 1;
1953  }
1954  return waited;
1955 }
1956 
1957 static int can_safely_quit(shutdown_nice_t niceness, int restart)
1958 {
1959  int waited = 0;
1960 
1961  /* Check if someone else isn't already doing this. */
1963  if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
1964  /* Already in progress and other request was less nice. */
1966  ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
1967  return 0;
1968  }
1969  shuttingdown = niceness;
1971 
1972  /* Try to get as many CDRs as possible submitted to the backend engines
1973  * (if in batch mode). really_quit happens to call it again when running
1974  * the atexit handlers, otherwise this would be a bit early. */
1976 
1977  /*
1978  * Shutdown the message queue for the technology agnostic message channel.
1979  * This has to occur before we pause shutdown pending ast_undestroyed_channels.
1980  *
1981  * XXX This is not reversed on shutdown cancel.
1982  */
1983  ast_msg_shutdown();
1984 
1985  if (niceness == SHUTDOWN_NORMAL) {
1986  /* Begin shutdown routine, hanging up active channels */
1988  if (ast_opt_console) {
1989  ast_verb(0, "Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
1990  }
1992  waited |= wait_for_channels_to_die(niceness, SHUTDOWN_TIMEOUT);
1993  } else if (niceness >= SHUTDOWN_NICE) {
1994  if (niceness != SHUTDOWN_REALLY_NICE) {
1996  }
1997  if (ast_opt_console) {
1998  ast_verb(0, "Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
1999  }
2000  waited |= wait_for_channels_to_die(niceness, -1);
2001  }
2002 
2003  /* Re-acquire lock and check if someone changed the niceness, in which
2004  * case someone else has taken over the shutdown.
2005  */
2007  if (shuttingdown != niceness) {
2009  ast_verb(0, "Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
2010  }
2012  return 0;
2013  }
2014 
2015  if (niceness >= SHUTDOWN_REALLY_NICE) {
2018 
2019  /* No more Mr. Nice guy. We are committed to shutting down now. */
2023 
2025  }
2028 
2029  if (niceness >= SHUTDOWN_NORMAL && waited) {
2030  /*
2031  * We were not idle. Give things in progress a chance to
2032  * recognize the final shutdown phase.
2033  */
2034  sleep(1);
2035  }
2036  return 1;
2037 }
2038 
2039 /*! Called when exiting is certain. */
2040 static void really_quit(int num, shutdown_nice_t niceness, int restart)
2041 {
2042  int active_channels;
2043  struct ast_json *json_object = NULL;
2044  int run_cleanups = niceness >= SHUTDOWN_NICE;
2045 
2046  if (run_cleanups && modules_shutdown()) {
2047  ast_verb(0, "Some modules could not be unloaded, switching to fast shutdown\n");
2048  run_cleanups = 0;
2049  }
2050 
2051  if (!restart) {
2052  ast_sd_notify("STOPPING=1");
2053  }
2056  if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
2057  /* Only end if we are the consolethread, otherwise there's a race with that thread. */
2058  if (el != NULL) {
2059  el_end(el);
2060  }
2061  if (el_hist != NULL) {
2062  history_end(el_hist);
2063  }
2064  } else if (!restart) {
2065  sig_flags.need_el_end = 1;
2066  pthread_kill(consolethread, SIGURG);
2067  }
2068  }
2069  active_channels = ast_active_channels();
2070  /* Don't publish messages if we're a remote console - we won't have all of the Stasis
2071  * topics or message types
2072  */
2073  if (!ast_opt_remote) {
2074  json_object = ast_json_pack("{s: s, s: s}",
2075  "Shutdown", active_channels ? "Uncleanly" : "Cleanly",
2076  "Restart", restart ? "True" : "False");
2077  ast_manager_publish_event("Shutdown", EVENT_FLAG_SYSTEM, json_object);
2078  ast_json_unref(json_object);
2079  json_object = NULL;
2080  }
2081  ast_verb(0, "Asterisk %s ending (%d).\n",
2082  active_channels ? "uncleanly" : "cleanly", num);
2083 
2084  ast_verb(0, "Executing last minute cleanups\n");
2085  ast_run_atexits(run_cleanups);
2086 
2087  ast_debug(1, "Asterisk ending (%d).\n", num);
2088  if (ast_socket > -1) {
2089  pthread_cancel(lthread);
2090  close(ast_socket);
2091  ast_socket = -1;
2092  if (!ast_socket_is_sd) {
2093  unlink(ast_config_AST_SOCKET);
2094  }
2095  pthread_kill(lthread, SIGURG);
2096  pthread_join(lthread, NULL);
2097  }
2098  if (ast_consock > -1)
2099  close(ast_consock);
2100  if (!ast_opt_remote)
2101  unlink(ast_config_AST_PID);
2103  printf("%s", term_quit());
2104  if (restart) {
2105  int i;
2106  ast_verb(0, "Preparing for Asterisk restart...\n");
2107  /* Mark all FD's for closing on exec */
2108  for (i = 3; i < 32768; i++) {
2109  fcntl(i, F_SETFD, FD_CLOEXEC);
2110  }
2111  ast_verb(0, "Asterisk is now restarting...\n");
2112  restartnow = 1;
2113 
2114  /* close logger */
2115  close_logger();
2116  clean_time_zones();
2117 
2118  /* If there is a consolethread running send it a SIGHUP
2119  so it can execvp, otherwise we can do it ourselves */
2120  if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
2121  pthread_kill(consolethread, SIGHUP);
2122  /* Give the signal handler some time to complete */
2123  sleep(2);
2124  } else
2125  execvp(_argv[0], _argv);
2126 
2127  } else {
2128  /* close logger */
2129  close_logger();
2130  clean_time_zones();
2131  }
2132 
2133  exit(0);
2134 }
2135 
2136 static void __quit_handler(int num)
2137 {
2138  sig_flags.need_quit = 1;
2140  fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
2141  }
2142  /* There is no need to restore the signal handler here, since the app
2143  * is going to exit */
2144 }
2145 
2146 static void __remote_quit_handler(int num)
2147 {
2148  sig_flags.need_quit = 1;
2149 }
2150 
2151 static void set_header(char *outbuf, int maxout, char level)
2152 {
2153  const char *cmp;
2154  char date[40];
2155 
2156  switch (level) {
2157  case 0: cmp = NULL;
2158  break;
2159  case 1: cmp = VERBOSE_PREFIX_1;
2160  break;
2161  case 2: cmp = VERBOSE_PREFIX_2;
2162  break;
2163  case 3: cmp = VERBOSE_PREFIX_3;
2164  break;
2165  default: cmp = VERBOSE_PREFIX_4;
2166  break;
2167  }
2168 
2169  if (ast_opt_timestamp) {
2170  struct ast_tm tm;
2171  struct timeval now = ast_tvnow();
2172  ast_localtime(&now, &tm, NULL);
2173  ast_strftime(date, sizeof(date), ast_logger_get_dateformat(), &tm);
2174  }
2175 
2176  snprintf(outbuf, maxout, "%s%s%s%s%s%s",
2177  ast_opt_timestamp ? "[" : "",
2178  ast_opt_timestamp ? date : "",
2179  ast_opt_timestamp ? "] " : "",
2180  cmp ? ast_term_color(COLOR_GRAY, 0) : "",
2181  cmp ? cmp : "",
2182  cmp ? ast_term_reset() : "");
2183 }
2184 
2187 };
2188 
2189 static int console_state_init(void *ptr)
2190 {
2191  struct console_state_data *state = ptr;
2192  state->verbose_line_level = 0;
2193  return 0;
2194 }
2195 
2197 
2198 static int console_print(const char *s)
2199 {
2200  struct console_state_data *state =
2202 
2203  char prefix[80];
2204  const char *c;
2205  int num, res = 0;
2206  unsigned int newline;
2207 
2208  do {
2209  if (VERBOSE_HASMAGIC(s)) {
2210 
2211  /* always use the given line's level, otherwise
2212  we'll use the last line's level */
2213  state->verbose_line_level = VERBOSE_MAGIC2LEVEL(s);
2214 
2215  /* move past magic */
2216  s++;
2217 
2218  set_header(prefix, sizeof(prefix), state->verbose_line_level);
2219  } else {
2220  *prefix = '\0';
2221  }
2222  c = s;
2223 
2224  /* for a given line separate on verbose magic, newline, and eol */
2225  if ((s = strchr(c, '\n'))) {
2226  ++s;
2227  newline = 1;
2228  } else {
2229  s = strchr(c, '\0');
2230  newline = 0;
2231  }
2232 
2233  /* check if we should write this line after calculating begin/end
2234  so we process the case of a higher level line embedded within
2235  two lower level lines */
2236  if (state->verbose_line_level > option_verbose) {
2237  continue;
2238  }
2239 
2240  if (!ast_strlen_zero(prefix)) {
2241  fputs(prefix, stdout);
2242  }
2243 
2244  num = s - c;
2245  if (fwrite(c, sizeof(char), num, stdout) < num) {
2246  break;
2247  }
2248 
2249  if (!res) {
2250  /* if at least some info has been written
2251  we'll want to return true */
2252  res = 1;
2253  }
2254  } while (*s);
2255 
2256  if (newline) {
2257  /* if ending on a newline then reset last level to zero
2258  since what follows may be not be logging output */
2259  state->verbose_line_level = 0;
2260  }
2261 
2262  if (res) {
2263  fflush(stdout);
2264  }
2265 
2266  return res;
2267 }
2268 
2269 static int ast_all_zeros(const char *s)
2270 {
2271  while (*s) {
2272  if (*s > 32)
2273  return 0;
2274  s++;
2275  }
2276  return 1;
2277 }
2278 
2279 /* This is the main console CLI command handler. Run by the main() thread. */
2280 static void consolehandler(const char *s)
2281 {
2282  printf("%s", term_end());
2283  fflush(stdout);
2284 
2285  /* Called when readline data is available */
2286  if (!ast_all_zeros(s))
2287  ast_el_add_history(s);
2288  /* The real handler for bang */
2289  if (s[0] == '!') {
2290  if (s[1])
2291  ast_safe_system(s+1);
2292  else
2293  ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2294  } else
2295  ast_cli_command(STDOUT_FILENO, s);
2296 }
2297 
2298 static int remoteconsolehandler(const char *s)
2299 {
2300  int ret = 0;
2301 
2302  /* Called when readline data is available */
2303  if (!ast_all_zeros(s))
2304  ast_el_add_history(s);
2305 
2306  while (isspace(*s)) {
2307  s++;
2308  }
2309 
2310  /* The real handler for bang */
2311  if (s[0] == '!') {
2312  if (s[1])
2313  ast_safe_system(s+1);
2314  else
2315  ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2316  ret = 1;
2317  } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
2318  (s[4] == '\0' || isspace(s[4]))) {
2319  quit_handler(0, SHUTDOWN_FAST, 0);
2320  ret = 1;
2321  }
2322 
2323  return ret;
2324 }
2325 
2326 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2327 {
2328  switch (cmd) {
2329  case CLI_INIT:
2330  e->command = "core show version";
2331  e->usage =
2332  "Usage: core show version\n"
2333  " Shows Asterisk version information.\n";
2334  return NULL;
2335  case CLI_GENERATE:
2336  return NULL;
2337  }
2338 
2339  if (a->argc != 3)
2340  return CLI_SHOWUSAGE;
2341  ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
2344  return CLI_SUCCESS;
2345 }
2346 
2347 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2348 {
2349  switch (cmd) {
2350  case CLI_INIT:
2351  e->command = "core stop now";
2352  e->usage =
2353  "Usage: core stop now\n"
2354  " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
2356  return NULL;
2357  case CLI_GENERATE:
2358  return NULL;
2359  }
2360 
2361  if (a->argc != e->args)
2362  return CLI_SHOWUSAGE;
2363  quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
2364  return CLI_SUCCESS;
2365 }
2366 
2367 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2368 {
2369  switch (cmd) {
2370  case CLI_INIT:
2371  e->command = "core stop gracefully";
2372  e->usage =
2373  "Usage: core stop gracefully\n"
2374  " Causes Asterisk to not accept new calls, and exit when all\n"
2375  " active calls have terminated normally.\n";
2377  return NULL;
2378  case CLI_GENERATE:
2379  return NULL;
2380  }
2381 
2382  if (a->argc != e->args)
2383  return CLI_SHOWUSAGE;
2384  quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
2385  return CLI_SUCCESS;
2386 }
2387 
2388 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2389 {
2390  switch (cmd) {
2391  case CLI_INIT:
2392  e->command = "core stop when convenient";
2393  e->usage =
2394  "Usage: core stop when convenient\n"
2395  " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2397  return NULL;
2398  case CLI_GENERATE:
2399  return NULL;
2400  }
2401 
2402  if (a->argc != e->args)
2403  return CLI_SHOWUSAGE;
2404  ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2405  quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2406  return CLI_SUCCESS;
2407 }
2408 
2409 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2410 {
2411  switch (cmd) {
2412  case CLI_INIT:
2413  e->command = "core restart now";
2414  e->usage =
2415  "Usage: core restart now\n"
2416  " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2417  " restart.\n";
2419  return NULL;
2420  case CLI_GENERATE:
2421  return NULL;
2422  }
2423 
2424  if (a->argc != e->args)
2425  return CLI_SHOWUSAGE;
2426  quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2427  return CLI_SUCCESS;
2428 }
2429 
2430 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2431 {
2432  switch (cmd) {
2433  case CLI_INIT:
2434  e->command = "core restart gracefully";
2435  e->usage =
2436  "Usage: core restart gracefully\n"
2437  " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2438  " restart when all active calls have ended.\n";
2440  return NULL;
2441  case CLI_GENERATE:
2442  return NULL;
2443  }
2444 
2445  if (a->argc != e->args)
2446  return CLI_SHOWUSAGE;
2447  quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2448  return CLI_SUCCESS;
2449 }
2450 
2451 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2452 {
2453  switch (cmd) {
2454  case CLI_INIT:
2455  e->command = "core restart when convenient";
2456  e->usage =
2457  "Usage: core restart when convenient\n"
2458  " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2460  return NULL;
2461  case CLI_GENERATE:
2462  return NULL;
2463  }
2464 
2465  if (a->argc != e->args)
2466  return CLI_SHOWUSAGE;
2467  ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2468  quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2469  return CLI_SUCCESS;
2470 }
2471 
2472 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2473 {
2474  switch (cmd) {
2475  case CLI_INIT:
2476  e->command = "core abort shutdown";
2477  e->usage =
2478  "Usage: core abort shutdown\n"
2479  " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2480  " call operations.\n";
2482  return NULL;
2483  case CLI_GENERATE:
2484  return NULL;
2485  }
2486 
2487  if (a->argc != e->args)
2488  return CLI_SHOWUSAGE;
2489 
2491 
2492  return CLI_SUCCESS;
2493 }
2494 
2495 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2496 {
2497  switch (cmd) {
2498  case CLI_INIT:
2499  e->command = "!";
2500  e->usage =
2501  "Usage: !<command>\n"
2502  " Executes a given shell command\n";
2503  return NULL;
2504  case CLI_GENERATE:
2505  return NULL;
2506  }
2507 
2508  return CLI_SUCCESS;
2509 }
2510 static const char warranty_lines[] = {
2511  "\n"
2512  " NO WARRANTY\n"
2513  "\n"
2514  "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2515  "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
2516  "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2517  "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2518  "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2519  "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
2520  "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
2521  "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2522  "REPAIR OR CORRECTION.\n"
2523  "\n"
2524  "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2525  "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2526  "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2527  "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2528  "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2529  "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2530  "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2531  "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2532  "POSSIBILITY OF SUCH DAMAGES.\n"
2533 };
2534 
2535 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2536 {
2537  switch (cmd) {
2538  case CLI_INIT:
2539  e->command = "core show warranty";
2540  e->usage =
2541  "Usage: core show warranty\n"
2542  " Shows the warranty (if any) for this copy of Asterisk.\n";
2543  return NULL;
2544  case CLI_GENERATE:
2545  return NULL;
2546  }
2547 
2548  ast_cli(a->fd, "%s", warranty_lines);
2549 
2550  return CLI_SUCCESS;
2551 }
2552 
2553 static const char license_lines[] = {
2554  "\n"
2555  "This program is free software; you can redistribute it and/or modify\n"
2556  "it under the terms of the GNU General Public License version 2 as\n"
2557  "published by the Free Software Foundation.\n"
2558  "\n"
2559  "This program also contains components licensed under other licenses.\n"
2560  "They include:\n"
2561  "\n"
2562  "This program is distributed in the hope that it will be useful,\n"
2563  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2564  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2565  "GNU General Public License for more details.\n"
2566  "\n"
2567  "You should have received a copy of the GNU General Public License\n"
2568  "along with this program; if not, write to the Free Software\n"
2569  "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
2570 };
2571 
2572 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2573 {
2574  switch (cmd) {
2575  case CLI_INIT:
2576  e->command = "core show license";
2577  e->usage =
2578  "Usage: core show license\n"
2579  " Shows the license(s) for this copy of Asterisk.\n";
2580  return NULL;
2581  case CLI_GENERATE:
2582  return NULL;
2583  }
2584 
2585  ast_cli(a->fd, "%s", license_lines);
2586 
2587  return CLI_SUCCESS;
2588 }
2589 
2590 #define ASTERISK_PROMPT "*CLI> "
2591 
2592 /*!
2593  * \brief Shutdown Asterisk CLI commands.
2594  *
2595  * \note These CLI commands cannot be unregistered at shutdown
2596  * because one of them is likely the reason for the shutdown.
2597  * The CLI generates a warning if a command is in-use when it is
2598  * unregistered.
2599  */
2600 static struct ast_cli_entry cli_asterisk_shutdown[] = {
2601  AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2602  AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2603  AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2604  AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2605  AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2606  AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2607 };
2608 
2609 static struct ast_cli_entry cli_asterisk[] = {
2610  AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2611  AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2612  AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2613  AST_CLI_DEFINE(handle_version, "Display version info"),
2614  AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2615 #if !defined(LOW_MEMORY)
2616  AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2617 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2618  AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2619 #endif
2620  AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2621  AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2622  AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2623 #endif /* ! LOW_MEMORY */
2624 };
2625 
2627 {
2628  char buf[80];
2629 
2630  /*
2631  * Tell the server asterisk instance about the verbose level
2632  * initially desired.
2633  */
2634  if (option_verbose) {
2635  snprintf(buf, sizeof(buf), "core set verbose atleast %d silent", option_verbose);
2637  }
2638 
2639  if (option_debug) {
2640  snprintf(buf, sizeof(buf), "core set debug atleast %d", option_debug);
2642  }
2643 
2644  /* Leave verbose filtering to the server. */
2645  option_verbose = INT_MAX;
2646 
2647  if (!ast_opt_mute) {
2648  fdsend(ast_consock, "logger mute silent");
2649  } else {
2650  printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2651  }
2652 }
2653 
2654 #ifdef HAVE_LIBEDIT_IS_UNICODE
2655 #define CHAR_T_LIBEDIT wchar_t
2656 #define CHAR_TO_LIBEDIT(c) btowc(c)
2657 #else
2658 #define CHAR_T_LIBEDIT char
2659 #define CHAR_TO_LIBEDIT(c) c
2660 #endif
2661 
2662 static int ast_el_read_char(EditLine *editline, CHAR_T_LIBEDIT *cp)
2663 {
2664  int num_read = 0;
2665  int lastpos = 0;
2666  struct pollfd fds[2];
2667  int res;
2668  int max;
2669 #define EL_BUF_SIZE 512
2670  char buf[EL_BUF_SIZE];
2671 
2672  for (;;) {
2673  max = 1;
2674  fds[0].fd = ast_consock;
2675  fds[0].events = POLLIN;
2676  if (!ast_opt_exec) {
2677  fds[1].fd = STDIN_FILENO;
2678  fds[1].events = POLLIN;
2679  max++;
2680  }
2681  res = ast_poll(fds, max, -1);
2682  if (res < 0) {
2683  if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
2684  break;
2685  }
2686  if (errno == EINTR) {
2687  continue;
2688  }
2689  fprintf(stderr, "poll failed: %s\n", strerror(errno));
2690  break;
2691  }
2692 
2693  if (!ast_opt_exec && fds[1].revents) {
2694  char c = '\0';
2695 
2696  num_read = read(STDIN_FILENO, &c, 1);
2697  if (num_read < 1) {
2698  break;
2699  }
2700 
2701  *cp = CHAR_TO_LIBEDIT(c);
2702 
2703  return num_read;
2704  }
2705 
2706  if (fds[0].revents) {
2707  res = read(ast_consock, buf, sizeof(buf) - 1);
2708  /* if the remote side disappears exit */
2709  if (res < 1) {
2710  fprintf(stderr, "\nDisconnected from Asterisk server\n");
2711  if (!ast_opt_reconnect) {
2712  quit_handler(0, SHUTDOWN_FAST, 0);
2713  } else {
2714  int tries;
2715  int reconnects_per_second = 20;
2716 
2717  fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2718  for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2719  if (ast_tryconnect()) {
2720  fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2721  printf("%s", term_quit());
2724  break;
2725  }
2726 
2727  usleep(1000000 / reconnects_per_second);
2728  }
2729  if (tries >= 30 * reconnects_per_second) {
2730  fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
2731  quit_handler(0, SHUTDOWN_FAST, 0);
2732  }
2733  }
2734  continue;
2735  }
2736 
2737  buf[res] = '\0';
2738 
2739  /* Write over the CLI prompt */
2740  if (!ast_opt_exec && !lastpos) {
2741  if (write(STDOUT_FILENO, "\r␛[0K", 5) < 0) {
2742  }
2743  }
2744 
2745  console_print(buf);
2746 
2747  if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (res >= 2 && buf[res-2] == '\n'))) {
2748  *cp = CHAR_TO_LIBEDIT(CC_REFRESH);
2749 
2750  return 1;
2751  }
2752  lastpos = 1;
2753  }
2754  }
2755 
2756  *cp = CHAR_TO_LIBEDIT('\0');
2757 
2758  return 0;
2759 }
2760 
2761 static struct ast_str *prompt = NULL;
2762 
2763 static char *cli_prompt(EditLine *editline)
2764 {
2765  char tmp[100];
2766  char *pfmt;
2767  int color_used = 0;
2768  static int cli_prompt_changes = 0;
2769  struct passwd *pw;
2770  struct group *gr;
2771 
2772  if (prompt == NULL) {
2773  prompt = ast_str_create(100);
2774  } else if (!cli_prompt_changes) {
2775  return ast_str_buffer(prompt);
2776  } else {
2778  }
2779 
2780  if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2781  char *t = pfmt;
2782  struct timeval ts = ast_tvnow();
2783  while (*t != '\0') {
2784  if (*t == '%') {
2785  char hostname[MAXHOSTNAMELEN] = "";
2786  int i, which;
2787  struct ast_tm tm = { 0, };
2788  int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2789 
2790  t++;
2791  switch (*t) {
2792  case 'C': /* color */
2793  t++;
2794  if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2795  ast_term_color_code(&prompt, fgcolor, bgcolor);
2796  t += i - 1;
2797  } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2798  ast_term_color_code(&prompt, fgcolor, 0);
2799  t += i - 1;
2800  }
2801 
2802  /* If the color has been reset correctly, then there's no need to reset it later */
2803  color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2804  break;
2805  case 'd': /* date */
2806  if (ast_localtime(&ts, &tm, NULL)) {
2807  ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2808  ast_str_append(&prompt, 0, "%s", tmp);
2809  cli_prompt_changes++;
2810  }
2811  break;
2812  case 'g': /* group */
2813  if ((gr = getgrgid(getgid()))) {
2814  ast_str_append(&prompt, 0, "%s", gr->gr_name);
2815  }
2816  break;
2817  case 'h': /* hostname */
2818  if (!gethostname(hostname, sizeof(hostname) - 1)) {
2819  ast_str_append(&prompt, 0, "%s", hostname);
2820  } else {
2821  ast_str_append(&prompt, 0, "%s", "localhost");
2822  }
2823  break;
2824  case 'H': /* short hostname */
2825  if (!gethostname(hostname, sizeof(hostname) - 1)) {
2826  char *dotptr;
2827  if ((dotptr = strchr(hostname, '.'))) {
2828  *dotptr = '\0';
2829  }
2830  ast_str_append(&prompt, 0, "%s", hostname);
2831  } else {
2832  ast_str_append(&prompt, 0, "%s", "localhost");
2833  }
2834  break;
2835 #ifdef HAVE_GETLOADAVG
2836  case 'l': /* load avg */
2837  t++;
2838  if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2839  double list[3];
2840  getloadavg(list, 3);
2841  ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2842  cli_prompt_changes++;
2843  }
2844  break;
2845 #endif
2846  case 's': /* Asterisk system name (from asterisk.conf) */
2848  break;
2849  case 't': /* time */
2850  if (ast_localtime(&ts, &tm, NULL)) {
2851  ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2852  ast_str_append(&prompt, 0, "%s", tmp);
2853  cli_prompt_changes++;
2854  }
2855  break;
2856  case 'u': /* username */
2857  if ((pw = getpwuid(getuid()))) {
2858  ast_str_append(&prompt, 0, "%s", pw->pw_name);
2859  }
2860  break;
2861  case '#': /* process console or remote? */
2862  ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2863  break;
2864  case '%': /* literal % */
2865  ast_str_append(&prompt, 0, "%c", '%');
2866  break;
2867  case '\0': /* % is last character - prevent bug */
2868  t--;
2869  break;
2870  }
2871  } else {
2872  ast_str_append(&prompt, 0, "%c", *t);
2873  }
2874  t++;
2875  }
2876  if (color_used) {
2877  /* Force colors back to normal at end */
2878  ast_term_color_code(&prompt, 0, 0);
2879  }
2880  } else {
2881  ast_str_set(&prompt, 0, "%s%s",
2883  ASTERISK_PROMPT);
2884  }
2885 
2886  return ast_str_buffer(prompt);
2887 }
2888 
2890 {
2891  char *retstr;
2892  struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
2893 
2894  if (!vec) {
2895  return NULL;
2896  }
2897 
2898  while ((retstr = strsep(&buf, " "))) {
2899  if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
2900  break;
2901  }
2902 
2903  retstr = ast_strdup(retstr);
2904  if (!retstr || AST_VECTOR_APPEND(vec, retstr)) {
2905  ast_free(retstr);
2906  goto vector_cleanup;
2907  }
2908  }
2909 
2910  if (!AST_VECTOR_SIZE(vec)) {
2911  goto vector_cleanup;
2912  }
2913 
2914  return vec;
2915 
2916 vector_cleanup:
2918  AST_VECTOR_PTR_FREE(vec);
2919 
2920  return NULL;
2921 }
2922 
2923 static void ast_cli_display_match_list(struct ast_vector_string *matches, int max)
2924 {
2925  int idx = 1;
2926  /* find out how many entries can be put on one line, with two spaces between strings */
2927  int limit = ast_get_termcols(STDOUT_FILENO) / (max + 2);
2928 
2929  if (limit == 0) {
2930  limit = 1;
2931  }
2932 
2933  for (;;) {
2934  int numoutputline;
2935 
2936  for (numoutputline = 0; numoutputline < limit && idx < AST_VECTOR_SIZE(matches); idx++) {
2937  numoutputline++;
2938  fprintf(stdout, "%-*s ", max, AST_VECTOR_GET(matches, idx));
2939  }
2940 
2941  if (!numoutputline) {
2942  break;
2943  }
2944 
2945  fprintf(stdout, "\n");
2946  }
2947 }
2948 
2949 
2950 static char *cli_complete(EditLine *editline, int ch)
2951 {
2952  int len = 0;
2953  char *ptr;
2954  struct ast_vector_string *matches;
2955  int retval = CC_ERROR;
2956  char savechr;
2957  int res;
2958 
2959  LineInfo *lf = (LineInfo *)el_line(editline);
2960 
2961  savechr = *(char *)lf->cursor;
2962  *(char *)lf->cursor = '\0';
2963  ptr = (char *)lf->cursor;
2964  if (ptr) {
2965  while (ptr > lf->buffer) {
2966  if (isspace(*ptr)) {
2967  ptr++;
2968  break;
2969  }
2970  ptr--;
2971  }
2972  }
2973 
2974  len = lf->cursor - ptr;
2975 
2976  if (ast_opt_remote) {
2977 #define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
2978  char *mbuf;
2979  char *new_mbuf;
2980  int mlen = 0;
2981  int maxmbuf = ast_asprintf(&mbuf, CMD_MATCHESARRAY, lf->buffer, ptr);
2982 
2983  if (maxmbuf == -1) {
2984  *((char *) lf->cursor) = savechr;
2985 
2986  return (char *)(CC_ERROR);
2987  }
2988 
2989  fdsend(ast_consock, mbuf);
2990  res = 0;
2991  mlen = 0;
2992  mbuf[0] = '\0';
2993 
2994  while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
2995  if (mlen + 1024 > maxmbuf) {
2996  /* Expand buffer to the next 1024 byte increment plus a NULL terminator. */
2997  maxmbuf = mlen + 1024;
2998  new_mbuf = ast_realloc(mbuf, maxmbuf + 1);
2999  if (!new_mbuf) {
3000  ast_free(mbuf);
3001  *((char *) lf->cursor) = savechr;
3002 
3003  return (char *)(CC_ERROR);
3004  }
3005  mbuf = new_mbuf;
3006  }
3007  /* Only read 1024 bytes at a time */
3008  res = read(ast_consock, mbuf + mlen, 1024);
3009  if (res > 0) {
3010  mlen += res;
3011  mbuf[mlen] = '\0';
3012  }
3013  }
3014  mbuf[mlen] = '\0';
3015 
3016  matches = ast_el_strtoarr(mbuf);
3017  ast_free(mbuf);
3018  } else {
3019  matches = ast_cli_completion_vector((char *)lf->buffer, ptr);
3020  }
3021 
3022  if (matches) {
3023  int i;
3024  int maxlen, match_len;
3025  const char *best_match = AST_VECTOR_GET(matches, 0);
3026 
3027  if (!ast_strlen_zero(best_match)) {
3028  el_deletestr(editline, (int) len);
3029  el_insertstr(editline, best_match);
3030  retval = CC_REFRESH;
3031  }
3032 
3033  if (AST_VECTOR_SIZE(matches) == 2) {
3034  /* Found an exact match */
3035  el_insertstr(editline, " ");
3036  retval = CC_REFRESH;
3037  } else {
3038  /* Must be more than one match */
3039  for (i = 1, maxlen = 0; i < AST_VECTOR_SIZE(matches); i++) {
3040  match_len = strlen(AST_VECTOR_GET(matches, i));
3041  if (match_len > maxlen) {
3042  maxlen = match_len;
3043  }
3044  }
3045 
3046  fprintf(stdout, "\n");
3047  ast_cli_display_match_list(matches, maxlen);
3048  retval = CC_REDISPLAY;
3049  }
3051  AST_VECTOR_PTR_FREE(matches);
3052  }
3053 
3054  *((char *) lf->cursor) = savechr;
3055 
3056  return (char *)(long)retval;
3057 }
3058 
3059 static int ast_el_initialize(void)
3060 {
3061  HistEvent ev;
3062  char *editor, *editrc = getenv("EDITRC");
3063 
3064  if (!(editor = getenv("AST_EDITMODE"))) {
3065  if (!(editor = getenv("AST_EDITOR"))) {
3066  editor = "emacs";
3067  }
3068  }
3069 
3070  if (el != NULL)
3071  el_end(el);
3072  if (el_hist != NULL)
3073  history_end(el_hist);
3074 
3075  el = el_init("asterisk", stdin, stdout, stderr);
3076  el_set(el, EL_PROMPT, cli_prompt);
3077 
3078  el_set(el, EL_EDITMODE, 1);
3079  el_set(el, EL_EDITOR, editor);
3080  el_hist = history_init();
3081  if (!el || !el_hist)
3082  return -1;
3083 
3084  /* setup history with 100 entries */
3085  history(el_hist, &ev, H_SETSIZE, 100);
3086 
3087  el_set(el, EL_HIST, history, el_hist);
3088 
3089  el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
3090  /* Bind <tab> to command completion */
3091  el_set(el, EL_BIND, "^I", "ed-complete", NULL);
3092  /* Bind ? to command completion */
3093  el_set(el, EL_BIND, "?", "ed-complete", NULL);
3094  /* Bind ^D to redisplay */
3095  el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
3096  /* Bind Delete to delete char left */
3097  el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
3098  /* Bind Home and End to move to line start and end */
3099  el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
3100  el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
3101  /* Bind C-left and C-right to move by word (not all terminals) */
3102  el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
3103  el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
3104 
3105  if (editrc) {
3106  el_source(el, editrc);
3107  }
3108 
3109  return 0;
3110 }
3111 
3112 #define MAX_HISTORY_COMMAND_LENGTH 256
3113 
3114 static int ast_el_add_history(const char *buf)
3115 {
3116  HistEvent ev;
3117  char *stripped_buf;
3118 
3119  if (el_hist == NULL || el == NULL) {
3121  }
3122  if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1)) {
3123  return 0;
3124  }
3125 
3126  stripped_buf = ast_strip(ast_strdupa(buf));
3127 
3128  /* HISTCONTROL=ignoredups */
3129  if (!history(el_hist, &ev, H_FIRST) && strcmp(ev.str, stripped_buf) == 0) {
3130  return 0;
3131  }
3132 
3133  return history(el_hist, &ev, H_ENTER, stripped_buf);
3134 }
3135 
3136 static int ast_el_write_history(const char *filename)
3137 {
3138  HistEvent ev;
3139 
3140  if (el_hist == NULL || el == NULL)
3142 
3143  return (history(el_hist, &ev, H_SAVE, filename));
3144 }
3145 
3146 static int ast_el_read_history(const char *filename)
3147 {
3148  HistEvent ev;
3149 
3150  if (el_hist == NULL || el == NULL) {
3152  }
3153 
3154  return history(el_hist, &ev, H_LOAD, filename);
3155 }
3156 
3158 {
3159  char histfile[80] = "";
3160  const char *home = getenv("HOME");
3161 
3162  if (!ast_strlen_zero(home)) {
3163  snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
3164  ast_el_read_history(histfile);
3165  }
3166 }
3167 
3169 {
3170  char histfile[80] = "";
3171  const char *home = getenv("HOME");
3172 
3173  if (!ast_strlen_zero(home)) {
3174  snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
3175  ast_el_write_history(histfile);
3176  }
3177 }
3178 
3179 static void ast_remotecontrol(char *data)
3180 {
3181  char buf[256] = "";
3182  int res;
3183  char *hostname;
3184  char *cpid;
3185  char *version;
3186  int pid;
3187  char *stringp = NULL;
3188 
3189  char *ebuf;
3190  int num = 0;
3191 
3192  ast_term_init();
3193  printf("%s", term_end());
3194  fflush(stdout);
3195 
3196  memset(&sig_flags, 0, sizeof(sig_flags));
3197  signal(SIGINT, __remote_quit_handler);
3198  signal(SIGTERM, __remote_quit_handler);
3199  signal(SIGHUP, __remote_quit_handler);
3200 
3201  if (read(ast_consock, buf, sizeof(buf) - 1) < 0) {
3202  ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
3203  return;
3204  }
3205  if (data) {
3206  char prefix[] = "cli quit after ";
3207  char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
3208  sprintf(tmp, "%s%s", prefix, data);
3209  if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
3210  ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
3211  if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3212  return;
3213  }
3214  }
3215  }
3216  stringp = buf;
3217  hostname = strsep(&stringp, "/");
3218  cpid = strsep(&stringp, "/");
3219  version = strsep(&stringp, "\n");
3220  if (!version)
3221  version = "<Version Unknown>";
3222  stringp = hostname;
3223  strsep(&stringp, ".");
3224  if (cpid)
3225  pid = atoi(cpid);
3226  else
3227  pid = -1;
3228  if (!data) {
3230  }
3231 
3232  if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
3233  int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
3234  struct pollfd fds;
3235  fds.fd = ast_consock;
3236  fds.events = POLLIN;
3237  fds.revents = 0;
3238 
3239  while (ast_poll(&fds, 1, 60000) > 0) {
3240  char buffer[512] = "", *curline = buffer, *nextline;
3241  int not_written = 1;
3242 
3243  if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3244  break;
3245  }
3246 
3247  if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
3248  break;
3249  }
3250 
3251  do {
3252  prev_linefull = linefull;
3253  if ((nextline = strchr(curline, '\n'))) {
3254  linefull = 1;
3255  nextline++;
3256  } else {
3257  linefull = 0;
3258  nextline = strchr(curline, '\0');
3259  }
3260 
3261  /* Skip verbose lines */
3262  /* Prev line full? | Line is verbose | Last line verbose? | Print
3263  * TRUE | TRUE* | TRUE | FALSE
3264  * TRUE | TRUE* | FALSE | FALSE
3265  * TRUE | FALSE* | TRUE | TRUE
3266  * TRUE | FALSE* | FALSE | TRUE
3267  * FALSE | TRUE | TRUE* | FALSE
3268  * FALSE | TRUE | FALSE* | TRUE
3269  * FALSE | FALSE | TRUE* | FALSE
3270  * FALSE | FALSE | FALSE* | TRUE
3271  */
3272  if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
3273  prev_line_verbose = 0;
3274  not_written = 0;
3275  if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
3276  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3277  }
3278  } else {
3279  prev_line_verbose = 1;
3280  }
3281  curline = nextline;
3282  } while (!ast_strlen_zero(curline));
3283 
3284  /* No non-verbose output in 60 seconds. */
3285  if (not_written) {
3286  break;
3287  }
3288  }
3289  return;
3290  }
3291 
3292  ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
3294 
3296  if (el_hist == NULL || el == NULL)
3299 
3300  el_set(el, EL_GETCFN, ast_el_read_char);
3301 
3302  for (;;) {
3303  ebuf = (char *)el_gets(el, &num);
3304 
3305  if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3306  break;
3307  }
3308 
3309  if (!ebuf && write(1, "", 1) < 0)
3310  break;
3311 
3312  if (!ast_strlen_zero(ebuf)) {
3313  if (ebuf[strlen(ebuf)-1] == '\n')
3314  ebuf[strlen(ebuf)-1] = '\0';
3315  if (!remoteconsolehandler(ebuf)) {
3316  res = write(ast_consock, ebuf, strlen(ebuf) + 1);
3317  if (res < 1) {
3318  ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
3319  break;
3320  }
3321  }
3322  }
3323  }
3324  printf("\nDisconnected from Asterisk server\n");
3325 }
3326 
3327 static int show_version(void)
3328 {
3329  printf("Asterisk %s\n", ast_get_version());
3330  return 0;
3331 }
3332 
3333 static int show_cli_help(void)
3334 {
3335  printf("Asterisk %s, " COPYRIGHT_TAG "\n", ast_get_version());
3336  printf("Usage: asterisk [OPTIONS]\n");
3337  printf("Valid Options:\n");
3338  printf(" -V Display version number and exit\n");
3339  printf(" -C <configfile> Use an alternate configuration file\n");
3340  printf(" -G <group> Run as a group other than the caller\n");
3341  printf(" -U <user> Run as a user other than the caller\n");
3342  printf(" -c Provide console CLI\n");
3343  printf(" -d Increase debugging (multiple d's = more debugging)\n");
3344 #if HAVE_WORKING_FORK
3345  printf(" -f Do not fork\n");
3346  printf(" -F Always fork\n");
3347 #endif
3348  printf(" -g Dump core in case of a crash\n");
3349  printf(" -h This help screen\n");
3350  printf(" -i Initialize crypto keys at startup\n");
3351  printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
3352  printf(" -M <value> Limit the maximum number of calls to the specified value\n");
3353  printf(" -m Mute debugging and console output on the console\n");
3354  printf(" -n Disable console colorization. Can be used only at startup.\n");
3355  printf(" -p Run as pseudo-realtime thread\n");
3356  printf(" -q Quiet mode (suppress output)\n");
3357  printf(" -r Connect to Asterisk on this machine\n");
3358  printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
3359  printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
3360  printf(" -t Record soundfiles in /var/tmp and move them where they\n");
3361  printf(" belong after they are done\n");
3362  printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3363  printf(" of output to the CLI. Cannot be used with remote console mode.\n\n");
3364  printf(" -v Increase verbosity (multiple v's = more verbose)\n");
3365  printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
3366  printf(" -X Enable use of #exec in asterisk.conf\n");
3367  printf(" -W Adjust terminal colors to compensate for a light background\n");
3368  printf("\n");
3369  return 0;
3370 }
3371 
3373 {
3374  struct ast_config *cfg;
3375  struct ast_variable *v;
3376  struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE | CONFIG_FLAG_NOREALTIME };
3377 
3380 
3381  cfg = ast_config_load2("pjproject.conf", "" /* core, can't reload */, config_flags);
3382  if (!cfg
3383  || cfg == CONFIG_STATUS_FILEUNCHANGED
3384  || cfg == CONFIG_STATUS_FILEINVALID) {
3385  /* We'll have to use defaults */
3386  return;
3387  }
3388 
3389  for (v = ast_variable_browse(cfg, "startup"); v; v = v->next) {
3390  if (!strcasecmp(v->name, "log_level")) {
3391  if (sscanf(v->value, "%30d", &ast_option_pjproject_log_level) != 1) {
3393  } else if (ast_option_pjproject_log_level < 0) {
3397  }
3398  } else if (!strcasecmp(v->name, "cache_pools")) {
3400  }
3401  }
3402 
3403  ast_config_destroy(cfg);
3404 }
3405 
3406 static void *monitor_sig_flags(void *unused)
3407 {
3408  for (;;) {
3409  struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
3410 
3411  ast_poll(&p, 1, -1);
3412  if (sig_flags.need_reload) {
3413  sig_flags.need_reload = 0;
3415  }
3416  if (sig_flags.need_quit) {
3417  sig_flags.need_quit = 0;
3418  if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
3419  sig_flags.need_quit_handler = 1;
3420  pthread_kill(consolethread, SIGURG);
3421  } else {
3423  }
3424  }
3426  }
3427 
3428  return NULL;
3429 }
3430 
3431 static void *canary_thread(void *unused)
3432 {
3433  struct stat canary_stat;
3434  struct timeval now;
3435 
3436  /* Give the canary time to sing */
3437  sleep(120);
3438 
3439  for (;;) {
3440  now = ast_tvnow();
3441  if (stat(canary_filename, &canary_stat) || now.tv_sec > canary_stat.st_mtime + 60) {
3443  "The canary is no more. He has ceased to be! "
3444  "He's expired and gone to meet his maker! "
3445  "He's a stiff! Bereft of life, he rests in peace. "
3446  "His metabolic processes are now history! He's off the twig! "
3447  "He's kicked the bucket. He's shuffled off his mortal coil, "
3448  "run down the curtain, and joined the bleeding choir invisible!! "
3449  "THIS is an EX-CANARY. (Reducing priority)\n");
3450  set_priority_all(0);
3451  pthread_exit(NULL);
3452  }
3453 
3454  /* Check the canary once a minute */
3455  sleep(60);
3456  }
3457 }
3458 
3459 /* Used by libc's atexit(3) function */
3460 static void canary_exit(void)
3461 {
3462  if (canary_pid > 0) {
3463  int status;
3464  kill(canary_pid, SIGKILL);
3465  waitpid(canary_pid, &status, 0);
3466  }
3467 }
3468 
3469 /* Execute CLI commands on startup. Run by main() thread. */
3470 static void run_startup_commands(void)
3471 {
3472  int fd;
3473  struct ast_config *cfg;
3474  struct ast_flags cfg_flags = { 0 };
3475  struct ast_variable *v;
3476 
3477  if (!(cfg = ast_config_load2("cli.conf", "" /* core, can't reload */, cfg_flags)))
3478  return;
3480  return;
3481  }
3482 
3483  fd = open("/dev/null", O_RDWR);
3484  if (fd < 0) {
3485  ast_config_destroy(cfg);
3486  return;
3487  }
3488 
3489  for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
3490  if (ast_true(v->value))
3491  ast_cli_command(fd, v->name);
3492  }
3493 
3494  close(fd);
3495  ast_config_destroy(cfg);
3496 }
3497 
3498 static void env_init(void)
3499 {
3500  setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
3501  setenv("AST_BUILD_HOST", ast_build_hostname, 1);
3502  setenv("AST_BUILD_DATE", ast_build_date, 1);
3503  setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
3504  setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
3505  setenv("AST_BUILD_OS", ast_build_os, 1);
3506  setenv("AST_BUILD_USER", ast_build_user, 1);
3507  setenv("AST_VERSION", ast_get_version(), 1);
3508 }
3509 
3510 static void print_intro_message(const char *runuser, const char *rungroup)
3511 {
3514  if (runuser) {
3515  ast_verbose("Running as user '%s'\n", runuser);
3516  }
3517  if (rungroup) {
3518  ast_verbose("Running under group '%s'\n", rungroup);
3519  }
3520  }
3521 }
3522 
3523 static void main_atexit(void)
3524 {
3526 }
3527 
3528 int main(int argc, char *argv[])
3529 {
3530  int c;
3531  int x;
3532  int isroot = 1, rundir_exists = 0;
3533  RAII_VAR(char *, runuser, NULL, ast_free);
3534  RAII_VAR(char *, rungroup, NULL, ast_free);
3535  RAII_VAR(char *, xarg, NULL, ast_free);
3536  struct rlimit l;
3537  static const char *getopt_settings = "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:";
3538 
3539  /* Remember original args for restart */
3540  if (argc > ARRAY_LEN(_argv) - 1) {
3541  fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
3542  argc = ARRAY_LEN(_argv) - 1;
3543  }
3544  for (x = 0; x < argc; x++)
3545  _argv[x] = argv[x];
3546  _argv[x] = NULL;
3547 
3548  if (geteuid() != 0)
3549  isroot = 0;
3550 
3551  /* if the progname is rasterisk consider it a remote console */
3552  if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
3554  }
3555  ast_mainpid = getpid();
3556 
3557  /* Process command-line options that effect asterisk.conf load. */
3558  while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3559  switch (c) {
3560  case 'X':
3562  break;
3563  case 'C':
3564  set_asterisk_conf_path(optarg);
3565  break;
3566  case 'd':
3567  option_debug++;
3568  break;
3569  case 'h':
3570  show_cli_help();
3571  exit(0);
3572  case 'R':
3573  case 'r':
3574  case 'x':
3575  /* ast_opt_remote is checked during config load. This is only part of what
3576  * these options do, see the second loop for the rest of the actions. */
3578  break;
3579  case 'V':
3580  show_version();
3581  exit(0);
3582  case 'v':
3583  option_verbose++;
3584  break;
3585  case '?':
3586  exit(1);
3587  }
3588  }
3589 
3590  /* Initialize env so it is available if #exec is used in asterisk.conf. */
3591  env_init();
3592 
3594 
3595  /* Update env to include any systemname that was set. */
3596  env_init();
3597 
3598  /*! \brief Check for options
3599  *
3600  * \todo Document these options
3601  */
3602  optind = 1;
3603  while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3604  /*!\note Please keep the ordering here to alphabetical, capital letters
3605  * first. This will make it easier in the future to select unused
3606  * option flags for new features. */
3607  switch (c) {
3608  case 'B': /* Force black background */
3611  break;
3612  case 'X':
3613  /* The command-line -X option enables #exec for asterisk.conf only. */
3614  break;
3615  case 'C':
3616  /* already processed. */
3617  break;
3618  case 'c':
3620  break;
3621  case 'd':
3622  /* already processed. */
3623  break;
3624 #if defined(HAVE_SYSINFO)
3625  case 'e':
3626  if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3627  option_minmemfree = 0;
3628  }
3629  break;
3630 #endif
3631 #if HAVE_WORKING_FORK
3632  case 'F':
3634  break;
3635  case 'f':
3637  break;
3638 #endif
3639  case 'G':
3640  rungroup = ast_strdup(optarg);
3641  break;
3642  case 'g':
3644  break;
3645  case 'h':
3646  /* already processed. */
3647  break;
3648  case 'I':
3649  fprintf(stderr,
3650  "NOTICE: The -I option is no longer needed.\n"
3651  " It will always be enabled if you have a timing module loaded.\n");
3652  break;
3653  case 'i':
3655  break;
3656  case 'L':
3657  if ((sscanf(optarg, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
3658  ast_option_maxload = 0.0;
3659  }
3660  break;
3661  case 'M':
3662  if ((sscanf(optarg, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
3663  ast_option_maxcalls = 0;
3664  }
3665  break;
3666  case 'm':
3668  break;
3669  case 'n':
3671  break;
3672  case 'p':
3674  break;
3675  case 'q':
3677  break;
3678  case 'R':
3680  break;
3681  case 'r':
3683  break;
3684  case 's':
3685  if (ast_opt_remote) {
3686  set_socket_path(optarg);
3687  }
3688  break;
3689  case 'T':
3691  break;
3692  case 't':
3694  break;
3695  case 'U':
3696  runuser = ast_strdup(optarg);
3697  break;
3698  case 'V':
3699  case 'v':
3700  /* already processed. */
3701  break;
3702  case 'W': /* White background */
3705  break;
3706  case 'x':
3707  /* -r is implied by -x so set the flags -r sets as well. */
3709 
3711  xarg = ast_strdup(optarg);
3712  break;
3713  case '?':
3714  /* already processed. */
3715  break;
3716  }
3717  }
3718 
3719  if (ast_opt_remote) {
3720  int didwarn = 0;
3721  optind = 1;
3722 
3723  /* Not all options can be used with remote console. Warn if they're used. */
3724  while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3725  switch (c) {
3726  /* okay to run with remote console */
3727  case 'B': /* force black background */
3728  case 'd': /* debug */
3729  case 'h': /* help */
3730  case 'I': /* obsolete timing option: warning already thrown if used */
3731  case 'L': /* max load */
3732  case 'M': /* max calls */
3733  case 'R': /* reconnect */
3734  case 'r': /* remote */
3735  case 's': /* set socket path */
3736  case 'V': /* version */
3737  case 'v': /* verbose */
3738  case 'W': /* white background */
3739  case 'x': /* remote execute */
3740  case '?': /* ? */
3741  break;
3742  /* can only be run when Asterisk is starting */
3743  case 'X': /* enables #exec for asterisk.conf only. */
3744  case 'C': /* set config path */
3745  case 'c': /* foreground console */
3746  case 'e': /* minimum memory free */
3747  case 'F': /* always fork */
3748  case 'f': /* no fork */
3749  case 'G': /* run group */
3750  case 'g': /* dump core */
3751  case 'i': /* init keys */
3752  case 'm': /* mute */
3753  case 'n': /* no color */
3754  case 'p': /* high priority */
3755  case 'q': /* quiet */
3756  case 'T': /* timestamp */
3757  case 't': /* cache record files */
3758  case 'U': /* run user */
3759  fprintf(stderr, "'%c' option is not compatible with remote console mode and has no effect.\n", c);
3760  didwarn = 1;
3761  }
3762  }
3763  if (didwarn) {
3764  fprintf(stderr, "\n"); /* if any warnings print out, make them stand out */
3765  }
3766  }
3767 
3768  /* For remote connections, change the name of the remote connection.
3769  * We do this for the benefit of init scripts (which need to know if/when
3770  * the main asterisk process has died yet). */
3771  if (ast_opt_remote) {
3772  strcpy(argv[0], "rasterisk");
3773  for (x = 1; x < argc; x++) {
3774  argv[x] = argv[0] + 10;
3775  }
3776  }
3777 
3779  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");
3780  }
3781 
3783  fprintf(stderr, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
3785  }
3786 
3787  if (ast_opt_dump_core) {
3788  memset(&l, 0, sizeof(l));
3789  l.rlim_cur = RLIM_INFINITY;
3790  l.rlim_max = RLIM_INFINITY;
3791  if (setrlimit(RLIMIT_CORE, &l)) {
3792  fprintf(stderr, "Unable to disable core size resource limit: %s\n", strerror(errno));
3793  }
3794  }
3795 
3796  if (getrlimit(RLIMIT_NOFILE, &l)) {
3797  fprintf(stderr, "Unable to check file descriptor limit: %s\n", strerror(errno));
3798  }
3799 
3800 #if !defined(CONFIGURE_RAN_AS_ROOT)
3801  /* Check if select(2) will run with more file descriptors */
3802  do {
3803  int fd, fd2;
3804  ast_fdset readers;
3805  struct timeval tv = { 0, };
3806 
3807  if (l.rlim_cur <= FD_SETSIZE) {
3808  /* The limit of select()able FDs is irrelevant, because we'll never
3809  * open one that high. */
3810  break;
3811  }
3812 
3813  if (!(fd = open("/dev/null", O_RDONLY))) {
3814  fprintf(stderr, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
3815  break; /* XXX Should we exit() here? XXX */
3816  }
3817 
3818  fd2 = ((l.rlim_cur > sizeof(readers) * 8) ? sizeof(readers) * 8 : l.rlim_cur) - 1;
3819  if (dup2(fd, fd2) < 0) {
3820  fprintf(stderr, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
3821  close(fd);
3822  break;
3823  }
3824 
3825  FD_ZERO(&readers);
3826  FD_SET(fd2, &readers);
3827  if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
3828  fprintf(stderr, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
3829  }
3830  ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3831  close(fd);
3832  close(fd2);
3833  } while (0);
3834 #elif defined(HAVE_VARIABLE_FDSET)
3835  ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3836 #endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
3837 
3838  if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
3840  if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
3842 
3843  /* Must install this signal handler up here to ensure that if the canary
3844  * fails to execute that it doesn't kill the Asterisk process.
3845  */
3846  sigaction(SIGCHLD, &child_handler, NULL);
3847 
3848  /* It's common on some platforms to clear /var/run at boot. Create the
3849  * socket file directory before we drop privileges. */
3850  if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
3851  if (errno == EEXIST) {
3852  rundir_exists = 1;
3853  } else {
3854  fprintf(stderr, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
3855  }
3856  }
3857 
3858 #ifndef __CYGWIN__
3859 
3860  if (isroot) {
3862  }
3863 
3864  if (isroot && rungroup) {
3865  struct group *gr;
3866  gr = getgrnam(rungroup);
3867  if (!gr) {
3868  fprintf(stderr, "No such group '%s'!\n", rungroup);
3869  exit(1);
3870  }
3871  if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
3872  fprintf(stderr, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
3873  }
3874  if (setgid(gr->gr_gid)) {
3875  fprintf(stderr, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
3876  exit(1);
3877  }
3878  if (setgroups(0, NULL)) {
3879  fprintf(stderr, "Unable to drop unneeded groups\n");
3880  exit(1);
3881  }
3882  }
3883 
3884  if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
3885 #ifdef HAVE_CAP
3886  int has_cap = 1;
3887 #endif /* HAVE_CAP */
3888  struct passwd *pw;
3889  pw = getpwnam(runuser);
3890  if (!pw) {
3891  fprintf(stderr, "No such user '%s'!\n", runuser);
3892  exit(1);
3893  }
3894  if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
3895  fprintf(stderr, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
3896  }
3897 #ifdef HAVE_CAP
3898  if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
3899  ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
3900  has_cap = 0;
3901  }
3902 #endif /* HAVE_CAP */
3903  if (!isroot && pw->pw_uid != geteuid()) {
3904  fprintf(stderr, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
3905  exit(1);
3906  }
3907  if (!rungroup) {
3908  if (setgid(pw->pw_gid)) {
3909  fprintf(stderr, "Unable to setgid to %d!\n", (int)pw->pw_gid);
3910  exit(1);
3911  }
3912  if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
3913  fprintf(stderr, "Unable to init groups for '%s'\n", runuser);
3914  exit(1);
3915  }
3916  }
3917  if (setuid(pw->pw_uid)) {
3918  fprintf(stderr, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
3919  exit(1);
3920  }
3921 #ifdef HAVE_CAP
3922  if (has_cap) {
3923  cap_t cap;
3924 
3925  cap = cap_from_text("cap_net_admin=eip");
3926 
3927  if (cap_set_proc(cap)) {
3928  fprintf(stderr, "Unable to install capabilities.\n");
3929  }
3930  if (cap_free(cap)) {
3931  fprintf(stderr, "Unable to drop capabilities.\n");
3932  }
3933  }
3934 #endif /* HAVE_CAP */
3935  }
3936 
3937 #endif /* __CYGWIN__ */
3938 
3939 #ifdef linux
3940  if (geteuid() && ast_opt_dump_core) {
3941  if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
3942  fprintf(stderr, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
3943  }
3944  }
3945 #endif
3946 
3947  {
3948 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
3949  char dir[PATH_MAX];
3950  if (!getcwd(dir, sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
3951  fprintf(stderr, "Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
3952  /* If we cannot access the CWD, then we couldn't dump core anyway,
3953  * so chdir("/") won't break anything. */
3954  if (chdir("/")) {
3955  /* chdir(/) should never fail, so this ends up being a no-op */
3956  fprintf(stderr, "chdir(\"/\") failed?!! %s\n", strerror(errno));
3957  }
3958  } else
3959 #endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
3961  /* Backgrounding, but no cores, so chdir won't break anything. */
3962  if (chdir("/")) {
3963  fprintf(stderr, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
3964  }
3965  }
3966  }
3967 
3968  /* Initial value of the maximum active system verbosity level. */
3970 
3971  if (ast_sd_get_fd_un(SOCK_STREAM, ast_config_AST_SOCKET) > 0) {
3972  ast_socket_is_sd = 1;
3973  }
3974 
3975  /* DO NOT perform check for existing daemon if systemd has CLI socket activation */
3976  if (!ast_socket_is_sd && ast_tryconnect()) {
3977  /* One is already running */
3978  if (ast_opt_remote) {
3979  multi_thread_safe = 1;
3980  if (ast_opt_exec) {
3981  ast_remotecontrol(xarg);
3982  quit_handler(0, SHUTDOWN_FAST, 0);
3983  exit(0);
3984  }
3985  ast_term_init();
3986  printf("%s", term_end());
3987  fflush(stdout);
3988 
3989  print_intro_message(runuser, rungroup);
3990  printf("%s", term_quit());
3992  quit_handler(0, SHUTDOWN_FAST, 0);
3993  exit(0);
3994  } else {
3995  fprintf(stderr, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
3996  printf("%s", term_quit());
3997  exit(1);
3998  }
3999  } else if (ast_opt_remote || ast_opt_exec) {
4000  fprintf(stderr, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
4001  printf("%s", term_quit());
4002  exit(1);
4003  }
4004 
4005 #ifdef HAVE_CAP
4006  child_cap = cap_from_text("cap_net_admin-eip");
4007 #endif
4008  /* Not a remote console? Start the daemon. */
4009  asterisk_daemon(isroot, runuser, rungroup);
4010 #ifdef HAS_CAP
4011  cap_free(child_cap);
4012 #endif
4013  return 0;
4014 }
4015 
4016 static inline void check_init(int init_result, const char *name)
4017 {
4018  if (init_result) {
4019  if (ast_is_logger_initialized()) {
4020  ast_log(LOG_ERROR, "%s initialization failed. ASTERISK EXITING!\n%s", name, term_quit());
4021  } else {
4022  fprintf(stderr, "%s initialization failed. ASTERISK EXITING!\n%s", name, term_quit());
4023  }
4024  ast_run_atexits(0);
4025  exit(init_result == -2 ? 2 : 1);
4026  }
4027 }
4028 
4029 static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup)
4030 {
4031  FILE *f;
4032  sigset_t sigs;
4033  int num;
4034  char *buf;
4035  char pbx_uuid[AST_UUID_STR_LEN];
4036 
4037  /* Set time as soon as possible */
4039 
4040  /* This needs to remain as high up in the initial start up as possible.
4041  * daemon causes a fork to occur, which has all sorts of unintended
4042  * consequences for things that interact with threads. This call *must*
4043  * occur before anything in Asterisk spawns or manipulates thread related
4044  * primitives. */
4045 #if HAVE_WORKING_FORK
4047 #ifndef HAVE_SBIN_LAUNCHD
4048  if (daemon(1, 0) < 0) {
4049  fprintf(stderr, "daemon() failed: %s\n", strerror(errno));
4050  } else {
4051  ast_mainpid = getpid();
4052  }
4053 #else
4054  fprintf(stderr, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
4055 #endif
4056  }
4057 #endif
4058 
4059  /* At this point everything has been forked successfully,
4060  * we have determined that we aren't attempting to connect to
4061  * an Asterisk instance, and that there isn't one already running. */
4062  multi_thread_safe = 1;
4063 
4065 
4066  /* Check whether high prio was succesfully set by us or some
4067  * other incantation. */
4068  if (has_priority()) {
4070  } else {
4072  }
4073 
4074  /* Spawning of astcanary must happen AFTER the call to daemon(3) */
4075  if (ast_opt_high_priority) {
4076  snprintf(canary_filename, sizeof(canary_filename), "%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
4077 
4078  /* Don't let the canary child kill Asterisk, if it dies immediately */
4079  sigaction(SIGPIPE, &ignore_sig_handler, NULL);
4080 
4081  canary_pid = fork();
4082  if (canary_pid == 0) {
4083  char canary_binary[PATH_MAX], ppid[12];
4084 
4085  /* Reset signal handler */
4086  signal(SIGCHLD, SIG_DFL);
4087  signal(SIGPIPE, SIG_DFL);
4088 
4090  ast_set_priority(0);
4091  snprintf(ppid, sizeof(ppid), "%d", (int) ast_mainpid);
4092 
4093  /* Use the astcanary binary that we installed */
4094  snprintf(canary_binary, sizeof(canary_binary), "%s/astcanary", ast_config_AST_SBIN_DIR);
4095  execl(canary_binary, "astcanary", canary_filename, ppid, (char *)NULL);
4096 
4097  /* Should never happen */
4098  _exit(1);
4099  } else if (canary_pid > 0) {
4100  pthread_t dont_care;
4102  }
4103 
4104  /* Kill the canary when we exit */
4106  }
4107 
4108  /* Blindly write the PID file. */
4109  unlink(ast_config_AST_PID);
4110  f = fopen(ast_config_AST_PID, "w");
4111  if (f) {
4112  fprintf(f, "%ld\n", (long)ast_mainpid);
4113  fclose(f);
4114  } else {
4115  fprintf(stderr, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
4116  }
4117 
4118  /* Initialize the terminal. Since all processes have been forked,
4119  * we can now start using the standard log messages.
4120  */
4121  ast_term_init();
4122  printf("%s", term_end());
4123  fflush(stdout);
4124 
4125  print_intro_message(runuser, rungroup);
4126 
4128 
4129  check_init(astobj2_init(), "AO2");
4130  check_init(ast_named_locks_init(), "Named Locks");
4131 
4132  if (ast_opt_console) {
4133  if (el_hist == NULL || el == NULL)
4136  }
4137 
4138 #ifdef AST_XML_DOCS
4139  /* Load XML documentation. */
4141 #endif
4142 
4143  check_init(astdb_init(), "ASTdb");
4144 
4145  ast_uuid_init();
4146 
4147  if (ast_pbx_uuid_get(pbx_uuid, sizeof(pbx_uuid))) {
4148  ast_uuid_generate_str(pbx_uuid, sizeof(pbx_uuid));
4149  ast_db_put("pbx", "UUID", pbx_uuid);
4150  }
4151  ast_verb(0, "PBX UUID: %s\n", pbx_uuid);
4152 
4153  check_init(ast_json_init(), "libjansson");
4154  ast_ulaw_init();
4155  ast_alaw_init();
4156  ast_utf8_init();
4157  tdd_init();
4158  callerid_init();
4160 
4161  check_init(ast_utils_init(), "Utilities");
4162  check_init(ast_tps_init(), "Task Processor Core");
4163  check_init(ast_fd_init(), "File Descriptor Debugging");
4164  check_init(ast_pbx_init(), "ast_pbx_init");
4165  check_init(aco_init(), "Configuration Option Framework");
4166  check_init(stasis_init(), "Stasis");
4167 #ifdef TEST_FRAMEWORK
4168  check_init(ast_test_init(), "Test Framework");
4169 #endif
4170  check_init(ast_translate_init(), "Translator Core");
4171 
4172  ast_aoc_cli_init();
4173 
4174  check_init(ast_sorcery_init(), "Sorcery");
4175  check_init(ast_codec_init(), "Codecs");
4176  check_init(ast_format_init(), "Formats");
4177  check_init(ast_format_cache_init(), "Format Cache");
4178  check_init(ast_codec_builtin_init(), "Built-in Codecs");
4179  check_init(ast_bucket_init(), "Bucket API");
4180  check_init(ast_stasis_system_init(), "Stasis system-level information");
4181  check_init(ast_endpoint_stasis_init(), "Stasis Endpoint");
4182 
4183  ast_makesocket();
4184  /* GCC 4.9 gives a bogus "right-hand operand of comma expression has
4185  * no effect" warning */
4186  (void) sigemptyset(&sigs);
4187  (void) sigaddset(&sigs, SIGHUP);
4188  (void) sigaddset(&sigs, SIGTERM);
4189  (void) sigaddset(&sigs, SIGINT);
4190  (void) sigaddset(&sigs, SIGPIPE);
4191  (void) sigaddset(&sigs, SIGWINCH);
4192  pthread_sigmask(SIG_BLOCK, &sigs, NULL);
4193  sigaction(SIGURG, &urg_handler, NULL);
4194  signal(SIGINT, __quit_handler);
4195  signal(SIGTERM, __quit_handler);
4196  sigaction(SIGHUP, &hup_handler, NULL);
4197  sigaction(SIGPIPE, &ignore_sig_handler, NULL);
4198 
4199  /* ensure that the random number generators are seeded with a different value every time
4200  Asterisk is started
4201  */
4202  srand((unsigned int) getpid() + (unsigned int) time(NULL));
4203  initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
4204 
4206 
4207  check_init(init_logger(), "Logger");
4208  check_init(ast_rtp_engine_init(), "RTP Engine");
4209 
4211 
4212  check_init(ast_timing_init(), "Timing");
4213  check_init(ast_ssl_init(), "SSL");
4215  check_init(ast_pj_init(), "Embedded PJProject");
4216  check_init(app_init(), "App Core");
4217  check_init(mwi_init(), "MWI Core");
4218  check_init(devstate_init(), "Device State Core");
4219  check_init(ast_msg_init(), "Messaging API");
4220  check_init(ast_channels_init(), "Channel");
4221  check_init(ast_endpoint_init(), "Endpoints");
4222  check_init(ast_pickup_init(), "Call Pickup");
4223  check_init(ast_bridging_init(), "Bridging");
4224  check_init(ast_parking_stasis_init(), "Parking Core");
4225  check_init(ast_device_state_engine_init(), "Device State Engine");
4226  check_init(ast_presence_state_engine_init(), "Presence State Engine");
4227  check_init(dns_core_init(), "DNS Resolver Core");
4228  check_init(ast_dns_system_resolver_init(), "Default DNS resolver");
4229  check_init(ast_security_stasis_init(), "Security Stasis Topic and Events");
4230  check_init(ast_image_init(), "Image");
4231  check_init(ast_file_init(), "Generic File Format Support");
4232  check_init(load_pbx(), "load_pbx");
4233  check_init(load_pbx_builtins(), "Builtin PBX Applications");
4234  check_init(load_pbx_functions_cli(), "PBX Functions Support");
4235  check_init(load_pbx_variables(), "PBX Variables Support");
4236  check_init(load_pbx_switch(), "PBX Switch Support");
4237  check_init(load_pbx_app(), "PBX Application Support");
4238  check_init(load_pbx_hangup_handler(), "PBX Hangup Handler Support");
4239  check_init(ast_local_init(), "Local Proxy Channel Driver");
4240 
4241  /* We should avoid most config loads before this point as they can't use realtime. */
4242  check_init(load_modules(), "Module");
4243 
4244  /*
4245  * This has to load after the dynamic modules load, as items in the media
4246  * cache can't be constructed from items in the AstDB without their
4247  * bucket backends.
4248  */
4249  check_init(ast_media_cache_init(), "Media Cache");
4250 
4251  /* loads the cli_permissions.conf file needed to implement cli restrictions. */
4252  ast_cli_perms_init(0);
4253 
4254  ast_stun_init();
4255 
4257 
4258  if (ast_opt_no_fork) {
4259  consolethread = pthread_self();
4260  }
4261 
4263 
4265 
4268 
4269  pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
4270 
4272 
4276 
4278  ast_sd_notify("READY=1");
4279 
4280  ast_verb(0, COLORIZE_FMT "\n", COLORIZE(COLOR_BRGREEN, 0, "Asterisk Ready."));
4281 
4283 
4284  if (ast_opt_console) {
4285  /* Console stuff now... */
4286  /* Register our quit function */
4287  char title[256];
4288  char hostname[MAXHOSTNAMELEN] = "";
4289 
4290  if (gethostname(hostname, sizeof(hostname) - 1)) {
4291  ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
4292  }
4293 
4295 
4296  set_icon("Asterisk");
4297  snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
4298  set_title(title);
4299 
4300  el_set(el, EL_GETCFN, ast_el_read_char);
4301 
4302  for (;;) {
4303  if (sig_flags.need_el_end) {
4304  el_end(el);
4305 
4306  return;
4307  }
4308 
4309  if (sig_flags.need_quit || sig_flags.need_quit_handler) {
4310  quit_handler(0, SHUTDOWN_FAST, 0);
4311  break;
4312  }
4313  buf = (char *) el_gets(el, &num);
4314 
4315  if (!buf && write(1, "", 1) < 0)
4316  return; /* quit */
4317 
4318  if (buf) {
4319  if (buf[strlen(buf)-1] == '\n')
4320  buf[strlen(buf)-1] = '\0';
4321 
4323  }
4324  }
4325  }
4326 
4327  /* Stall until a quit signal is given */
4329 }
Prototypes for public functions only of internal interest,.
int load_pbx_variables(void)
void threadstorage_init(void)
Definition: threadstorage.c:35
void ast_process_pending_reloads(void)
Process reload requests received during startup.
Definition: loader.c:1407
int modules_shutdown(void)
Definition: loader.c:1182
int ast_bridging_init(void)
Initialize the bridging system.
Definition: bridge.c:5528
void dnsmgr_start_refresh(void)
Definition: dnsmgr.c:302
int ast_timing_init(void)
Definition: timing.c:289
int ast_device_state_engine_init(void)
Initialize the device state engine in separate thread.
Definition: devicestate.c:618
int ast_term_init(void)
Definition: term.c:165
int load_modules(void)
Definition: loader.c:2338
void ast_msg_shutdown(void)
void logger_queue_start(void)
Start the ast_queue_log() logger.
Definition: logger.c:1940
int aco_init(void)
void load_asterisk_conf(void)
Definition: options.c:210
int ast_test_init(void)
Definition: test.c:1222
void close_logger(void)
Definition: logger.c:1998
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
Definition: stun.c:576
void set_asterisk_conf_path(const char *path)
Definition: options.c:200
int astdb_init(void)
Definition: main/db.c:1082
int ast_pj_init(void)
Definition: libasteriskpj.c:45
int load_pbx_functions_cli(void)
int ast_tps_init(void)
void load_astmm_phase_2(void)
Initialize malloc debug phase 2.
Definition: astmm.c:1529
int ast_msg_init(void)
int load_pbx_hangup_handler(void)
int ast_local_init(void)
Initialize the local proxy channel.
Definition: core_local.c:1134
int load_pbx_builtins(void)
int load_pbx_switch(void)
Definition: pbx_switch.c:125
int ast_rtp_engine_init(void)
initializes the rtp engine arrays
Definition: rtp_engine.c:3615
int ast_xmldoc_load_documentation(void)
Load XML documentation. Provided by xmldoc.c.
Definition: xmldoc.c:2881
int ast_named_locks_init(void)
Definition: named_locks.c:52
int ast_channels_init(void)
Definition: channel.c:8090
void clean_time_zones(void)
Definition: localtime.c:1590
void load_astmm_phase_1(void)
Initialize malloc debug phase 1.
Definition: astmm.c:1525
void ast_builtins_init(void)
initialize the _full_cmd string in * each of the builtins.
Definition: main/cli.c:2243
void ast_autoservice_init(void)
Definition: autoservice.c:380
int init_logger(void)
Definition: logger.c:1956
int ast_endpoint_init(void)
Endpoint support initialization.
int dns_core_init(void)
Definition: dns_core.c:614
int load_pbx(void)
int astobj2_init(void)
Definition: astobj2.c:1169
int load_pbx_app(void)
Definition: pbx_app.c:511
int ast_dns_system_resolver_init(void)
Initializes the resolver.
int ast_ssl_init(void)
int ast_cli_perms_init(int reload)
Definition: main/cli.c:2115
void set_socket_path(const char *path)
Definition: options.c:205
int ast_file_init(void)
Definition: file.c:2024
int ast_parking_stasis_init(void)
initializes the rtp engine arrays
Definition: parking.c:53
Access Control of various sorts.
A-Law to Signed linear conversion.
void ast_alaw_init(void)
To init the alaw to slinear conversion stuff, this needs to be run.
Definition: alaw.c:152
void ast_alertpipe_close(int alert_pipe[2])
Close an alert pipe.
Definition: alertpipe.c:79
ssize_t ast_alertpipe_write(int alert_pipe[2])
Write an event to an alert pipe.
Definition: alertpipe.c:120
int ast_alertpipe_init(int alert_pipe[2])
Initialize an alert pipe.
Definition: alertpipe.c:38
ast_alert_status_t ast_alertpipe_read(int alert_pipe[2])
Read an event from an alert pipe.
Definition: alertpipe.c:102
Generic Advice of Charge encode and decode routines.
int ast_aoc_cli_init(void)
enable aoc cli options
Definition: aoc.c:2020
jack_status_t status
Definition: app_jack.c:146
char * text
Definition: app_queue.c:1641
enum queue_result id
Definition: app_queue.c:1640
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
Asterisk version information.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
const char * ast_get_build_opts(void)
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:412
static int ast_el_add_history(const char *)
Definition: asterisk.c:3114
static char * remotehostname
Definition: asterisk.c:341
static void __ast_unregister_atexit(void(*func)(void))
Definition: asterisk.c:1015
int64_t ast_mark(int i, int startstop)
Definition: asterisk.c:871
int main(int argc, char *argv[])
Definition: asterisk.c:3528
static int ast_socket_is_sd
Definition: asterisk.c:313
int ast_shutdown_final(void)
Definition: asterisk.c:1865
static void canary_exit(void)
Definition: asterisk.c:3460
static shutdown_nice_t shuttingdown
Definition: asterisk.c:378
static void check_init(int init_result, const char *name)
Definition: asterisk.c:4016
static void __remote_quit_handler(int num)
Definition: asterisk.c:2146
static void _urg_handler(int num)
Urgent handler.
Definition: asterisk.c:1705
static char * show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2572
#define CHAR_T_LIBEDIT
Definition: asterisk.c:2655
static void * canary_thread(void *unused)
Definition: asterisk.c:3431
static void ast_run_atexits(int run_cleanups)
Definition: asterisk.c:1001
static int console_state_init(void *ptr)
Definition: asterisk.c:2189
static struct profile_data * prof_data
Definition: asterisk.c:790
static int remoteconsolehandler(const char *s)
Definition: asterisk.c:2298
static struct ast_str * prompt
Definition: asterisk.c:2761
unsigned int need_reload
Definition: asterisk.c:398
static char * handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2409
static void publish_fully_booted(void)
Definition: asterisk.c:975
static int show_version(void)
Definition: asterisk.c:3327
static char * handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2495
static void main_atexit(void)
Definition: asterisk.c:3523
static int safe_exec_wait(pid_t pid)
wait for spawned application to complete and unreplace sigchld
Definition: asterisk.c:1190
static char * cli_complete(EditLine *editline, int ch)
Definition: asterisk.c:2950
int ast_add_profile(const char *name, uint64_t scale)
allocates a counter with a given name and scale.
Definition: asterisk.c:796
static void ast_cli_display_match_list(struct ast_vector_string *matches, int max)
Definition: asterisk.c:2923
static void _hup_handler(int num)
Definition: asterisk.c:1714
static pthread_t lthread
Definition: asterisk.c:1360
static unsigned int safe_system_level
Keep track of how many threads are currently trying to wait*() on a child process.
Definition: asterisk.c:1095
static void ast_network_puts_mutable(const char *string, int level, int sublevel)
log the string to all attached network console clients
Definition: asterisk.c:1291
static char randompool[256]
Definition: asterisk.c:390
static char * handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:601
static char * handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2451
#define WELCOME_MESSAGE
Welcome message when starting a CLI interface.
Definition: asterisk.c:303
int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1216
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: asterisk.c:1053
static void set_header(char *outbuf, int maxout, char level)
Definition: asterisk.c:2151
static int ast_el_read_char(EditLine *editline, CHAR_T_LIBEDIT *cp)
Definition: asterisk.c:2662
static char canary_filename[128]
Definition: asterisk.c:387
#define CMD_MATCHESARRAY
static __inline uint64_t rdtsc(void)
Definition: asterisk.c:864
static struct sigaction child_handler
Definition: asterisk.c:1753
int ast_set_priority(int pri)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1835
static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup)
Definition: asterisk.c:4029
void ast_console_toggle_loglevel(int fd, int level, int state)
enable or disable a logging level to a specified console
Definition: asterisk.c:1245
static int has_priority(void)
Check whether we were set to high(er) priority.
Definition: asterisk.c:1772
#define PF_LOCAL
Definition: asterisk.c:293
unsigned int need_el_end
Definition: asterisk.c:401
void ast_console_toggle_mute(int fd, int silent)
mute or unmute a console from logging
Definition: asterisk.c:1268
static void send_rasterisk_connect_commands(void)
Definition: asterisk.c:2626
unsigned int need_quit
Definition: asterisk.c:399
#define ASTERISK_PROMPT
Definition: asterisk.c:2590
static struct sigaction safe_system_prev_handler
Definition: asterisk.c:1096
static struct sigaction hup_handler
Definition: asterisk.c:1733
static pthread_t mon_sig_flags
Definition: asterisk.c:385
static int fdprint(int fd, const char *s)
Definition: asterisk.c:1072
static void * netconsole(void *vconsole)
Definition: asterisk.c:1422
static pthread_t consolethread
Definition: asterisk.c:384
static struct ast_vector_string * ast_el_strtoarr(char *buf)
Definition: asterisk.c:2889
static char * show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2535
static EditLine * el
Definition: asterisk.c:340
static int ast_el_initialize(void)
Definition: asterisk.c:3059
static int set_priority_all(int pri)
Set priority on all known threads.
Definition: asterisk.c:1792
static void * monitor_sig_flags(void *unused)
Definition: asterisk.c:3406
static void ast_begin_shutdown(void)
Definition: asterisk.c:1893
static int ast_el_read_history(const char *)
Definition: asterisk.c:3146
int ast_shutting_down(void)
Definition: asterisk.c:1870
static void _child_handler(int sig)
Definition: asterisk.c:1738
void ast_console_puts_mutable(const char *string, int level)
log the string to the root console, and all attached network console clients
Definition: asterisk.c:1310
static char * handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2367
#define AST_MAX_CONNECTS
Definition: asterisk.c:296
int ast_pbx_uuid_get(char *pbx_uuid, int length)
Retrieve the PBX UUID.
Definition: asterisk.c:970
void ast_replace_sigchld(void)
Replace the SIGCHLD handler.
Definition: asterisk.c:1098
int ast_cancel_shutdown(void)
Cancel an existing shutdown and return to normal operation.
Definition: asterisk.c:1875
static void ast_network_puts(const char *string)
write the string to all attached console clients
Definition: asterisk.c:1334
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:1372
#define CHAR_TO_LIBEDIT(c)
Definition: asterisk.c:2656
static char * cli_prompt(EditLine *editline)
Definition: asterisk.c:2763
static int shutdown_pending
Definition: asterisk.c:381
static void _null_sig_handler(int sig)
NULL handler so we can collect the child exit status.
Definition: asterisk.c:1078
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:667
static int sig_alert_pipe[2]
Definition: asterisk.c:396
struct timeval ast_lastreloadtime
Definition: asterisk.c:337
static const char warranty_lines[]
Definition: asterisk.c:2510
void ast_console_puts(const char *string)
write the string to the root console, and all attached network console clients
Definition: asterisk.c:1350
void ast_unregister_atexit(void(*func)(void))
Unregister a function registered with ast_register_atexit().
Definition: asterisk.c:1058
static int console_print(const char *s)
Definition: asterisk.c:2198
static void quit_handler(int num, shutdown_nice_t niceness, int restart)
Definition: asterisk.c:1905
static char * handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2326
static History * el_hist
Definition: asterisk.c:339
#define COPYRIGHT_TAG
Definition: asterisk.c:300
#define EL_BUF_SIZE
#define MAX_HISTORY_COMMAND_LENGTH
Definition: asterisk.c:3112
void ast_register_thread(char *name)
Definition: asterisk.c:414
static void ast_remotecontrol(char *data)
Definition: asterisk.c:3179
static int restartnow
Definition: asterisk.c:383
static int print_file(int fd, char *desc, const char *filename)
Print the contents of a file.
Definition: asterisk.c:450
void ast_unregister_thread(void *id)
Definition: asterisk.c:430
static void consolehandler(const char *s)
Definition: asterisk.c:2280
static struct ast_cli_entry cli_asterisk_shutdown[]
Shutdown Asterisk CLI commands.
Definition: asterisk.c:2600
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:1048
shutdown_nice_t
Definition: asterisk.c:356
@ SHUTDOWN_FAST
Definition: asterisk.c:369
@ SHUTDOWN_NORMAL
Definition: asterisk.c:371
@ SHUTDOWN_NICE
Definition: asterisk.c:373
@ SHUTDOWN_REALLY_NICE
Definition: asterisk.c:375
@ SHUTTING_DOWN
Definition: asterisk.c:362
@ SHUTTING_DOWN_FINAL
Definition: asterisk.c:360
@ NOT_SHUTTING_DOWN
Definition: asterisk.c:358
static ast_mutex_t safe_system_lock
Definition: asterisk.c:1091
static pid_t safe_exec_prep(int dualfork)
fork and perform other preparations for spawning applications
Definition: asterisk.c:1129
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: asterisk.c:1229
static int ast_all_zeros(const char *s)
Definition: asterisk.c:2269
static char * handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:940
#define SHUTDOWN_TIMEOUT
Definition: asterisk.c:1914
static int can_safely_quit(shutdown_nice_t niceness, int restart)
Definition: asterisk.c:1957
static struct @327 sig_flags
static void set_title(char *text)
Set an X-term or screen title.
Definition: asterisk.c:1759
static char * _argv[256]
Definition: asterisk.c:354
static int register_atexit(void(*func)(void), int is_cleanup)
Definition: asterisk.c:1029
static int wait_for_channels_to_die(shutdown_nice_t niceness, int seconds)
Definition: asterisk.c:1927
static struct ast_threadstorage console_state
Definition: asterisk.c:2196
static int ast_makesocket(void)
Definition: asterisk.c:1592
#define DEFINE_PROFILE_MIN_MAX_VALUES
Definition: asterisk.c:892
unsigned int need_quit_handler
Definition: asterisk.c:400
static int canary_pid
Definition: asterisk.c:386
static int ast_tryconnect(void)
Definition: asterisk.c:1678
static struct ast_cli_entry cli_asterisk[]
Definition: asterisk.c:2609
static int fdsend(int fd, const char *s)
Definition: asterisk.c:1066
static int ast_el_write_history(const char *)
Definition: asterisk.c:3136
static void run_startup_commands(void)
Definition: asterisk.c:3470
static int show_cli_help(void)
Definition: asterisk.c:3333
static char * handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2472
static void ast_el_read_default_histfile(void)
Definition: asterisk.c:3157
static char * handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2430
static void env_init(void)
Definition: asterisk.c:3498
static char * handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2388
static int ast_consock
Definition: asterisk.c:314
static char * handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:905
struct timeval ast_startuptime
Definition: asterisk.c:336
static void read_pjproject_startup_options(void)
Definition: asterisk.c:3372
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:467
static const char license_lines[]
Definition: asterisk.c:2553
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
Definition: asterisk.c:1113
static void * listener(void *unused)
Definition: asterisk.c:1512
static void really_quit(int num, shutdown_nice_t niceness, int restart)
Definition: asterisk.c:2040
static int ast_socket
Definition: asterisk.c:312
pid_t ast_mainpid
Definition: asterisk.c:315
static void ast_el_write_default_histfile(void)
Definition: asterisk.c:3168
#define AF_LOCAL
Definition: asterisk.c:292
static int multi_thread_safe
Definition: asterisk.c:388
static void __quit_handler(int num)
Definition: asterisk.c:2136
static char * handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2347
void ast_console_puts_mutable_full(const char *message, int level, int sublevel)
log the string to the console, and all attached console clients
Definition: asterisk.c:1317
static void set_icon(char *text)
Definition: asterisk.c:1765
static void print_intro_message(const char *runuser, const char *rungroup)
Definition: asterisk.c:3510
static struct sigaction ignore_sig_handler
Definition: asterisk.c:1087
static struct sigaction null_sig_handler
Definition: asterisk.c:1082
struct console consoles[AST_MAX_CONNECTS]
Definition: asterisk.c:343
int64_t ast_profile(int i, int64_t delta)
Definition: asterisk.c:830
static struct sigaction urg_handler
Definition: asterisk.c:1710
Asterisk main include file. File version handling, generic pbx functions.
#define sched_setscheduler
Definition: asterisk.h:51
int ast_pbx_init(void)
#define setpriority
Definition: asterisk.h:50
int ast_fd_init(void)
Definition: astfd.c:370
#define PATH_MAX
Definition: asterisk.h:40
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
Bucket File API.
int ast_bucket_init(void)
Initialize bucket support.
Definition: bucket.c:954
const char * ast_build_os
Definition: buildinfo.c:32
const char * ast_build_machine
Definition: buildinfo.c:31
const char * ast_build_hostname
Definition: buildinfo.c:29
const char * ast_build_user
Definition: buildinfo.c:34
const char * ast_build_date
Definition: buildinfo.c:33
const char * ast_build_kernel
Definition: buildinfo.c:30
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void callerid_init(void)
CallerID Initialization.
Definition: callerid.c:115
Call Detail Record API.
int ast_cdr_is_enabled(void)
Return TRUE if CDR subsystem is enabled.
Definition: cdr.c:2883
void ast_cdr_engine_term(void)
Definition: cdr.c:4597
static const char desc[]
Definition: cdr_radius.c:84
static PGresult * result
Definition: cel_pgsql.c:84
static int mute
Definition: chan_alsa.c:148
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
General Asterisk PBX channel definitions.
void ast_softhangup_all(void)
Soft hangup all active channels.
Definition: channel.c:493
int ast_undestroyed_channels(void)
Definition: channel.c:504
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_CLI_COMPLETE_EOF
Definition: cli.h:52
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
struct ast_vector_string * ast_cli_completion_vector(const char *text, const char *word)
Generates a vector of strings for CLI completion.
Definition: main/cli.c:2765
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
Definition: main/cli.c:3060
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: main/cli.c:3038
ast_cli_command
calling arguments for new-style handlers.
Definition: cli.h:151
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
Codec API.
int ast_codec_init(void)
Initialize codec support within the core.
Definition: codec.c:249
int ast_codec_builtin_init(void)
Initialize built-in codecs within the core.
Device state management.
int devstate_init(void)
Initialize the device state core.
Definition: devicestate.c:896
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Endpoint abstractions.
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define min(a, b)
Definition: f2c.h:197
#define max(a, b)
Definition: f2c.h:198
Generic File Format Support. Should be included by clients of the file handling routines....
Media Format API.
int ast_format_init(void)
Initialize media format support.
Definition: format.c:77
Media Format Cache API.
int ast_format_cache_init(void)
Initialize format cache support within the core.
Definition: format_cache.c:364
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_manager_check_enabled(void)
Check if AMI is enabled.
Definition: manager.c:1956
int ast_webmanager_check_enabled(void)
Check if AMI/HTTP is enabled.
Definition: manager.c:1961
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:1910
int ast_option_rtpusedynamic
Definition: options.c:88
int ast_option_maxfiles
Definition: options.c:81
int option_debug
Definition: options.c:69
int ast_verb_sys_level
Definition: options.c:64
int ast_option_maxcalls
Definition: options.c:79
int ast_option_pjproject_log_level
Definition: options.c:74
double ast_option_maxload
Definition: options.c:77
unsigned int ast_option_rtpptdynamic
Definition: options.c:89
int option_verbose
Definition: options.c:67
struct ast_flags ast_options
Definition: options.c:61
unsigned int option_dtmfminduration
Definition: options.c:83
int ast_option_pjproject_cache_pools
Definition: options.c:75
long option_minmemfree
Definition: options.c:86
int option_trace
Definition: options.c:71
@ AST_OPT_FLAG_HIGH_PRIORITY
Definition: options.h:48
@ AST_OPT_FLAG_GENERIC_PLC
Definition: options.h:98
@ AST_OPT_FLAG_TRANSCODE_VIA_SLIN
Definition: options.h:60
@ AST_OPT_FLAG_EXEC_INCLUDES
Definition: options.h:40
@ AST_OPT_FLAG_NO_COLOR
Definition: options.h:56
@ AST_OPT_FLAG_NO_FORK
Definition: options.h:42
@ AST_OPT_FLAG_TRANSMIT_SILENCE
Definition: options.h:74
@ AST_OPT_FLAG_ALWAYS_FORK
Definition: options.h:80
@ AST_OPT_FLAG_QUIET
Definition: options.h:44
@ AST_OPT_FLAG_GENERIC_PLC_ON_EQUAL_CODECS
Definition: options.h:100
@ AST_OPT_FLAG_MUTE
Definition: options.h:82
@ AST_OPT_FLAG_TIMESTAMP
Definition: options.h:68
@ AST_OPT_FLAG_EXEC
Definition: options.h:54
@ AST_OPT_FLAG_CACHE_RECORD_FILES
Definition: options.h:66
@ AST_OPT_FLAG_FULLY_BOOTED
Definition: options.h:58
@ AST_OPT_FLAG_INIT_KEYS
Definition: options.h:50
@ AST_OPT_FLAG_CONSOLE
Definition: options.h:46
@ AST_OPT_FLAG_FORCE_BLACK_BACKGROUND
Definition: options.h:92
@ AST_OPT_FLAG_LIGHT_BACKGROUND
Definition: options.h:88
@ AST_OPT_FLAG_REMOTE
Definition: options.h:52
@ AST_OPT_FLAG_DUMP_CORE
Definition: options.h:64
@ AST_OPT_FLAG_RECONNECT
Definition: options.h:72
static ENTRY retval
Definition: hsearch.c:50
static char prefix[MAX_PREFIX]
Definition: http.c:144
General Asterisk channel definitions for image handling.
int ast_image_init(void)
Initialize image stuff Initializes all the various image stuff. Basically just registers the cli stuf...
Definition: image.c:212
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
int app_init(void)
Initialize the application core.
Definition: main/app.c:3425
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: main/app.c:3262
int setenv(const char *name, const char *value, int overwrite)
int getloadavg(double *list, int nelem)
char * strsep(char **str, const char *delims)
Configuration File Parser.
#define CONFIG_STATUS_FILEMISSING
int ast_realtime_enabled(void)
Check if there's any realtime engines loaded.
Definition: main/config.c:3443
@ CONFIG_FLAG_NOCACHE
@ CONFIG_FLAG_NOREALTIME
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3220
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
int register_config_cli(void)
Exposed initialization method for core process.
Definition: main/config.c:4135
#define VERBOSE_PREFIX_3
void ast_verb_console_unregister(void)
Unregister this thread's console verbosity level.
Definition: logger.c:2396
void ast_verb_console_register(int *level)
Register this thread's console verbosity level pointer.
Definition: logger.c:2380
#define NUMLOGLEVELS
#define ast_debug(level,...)
Log a DEBUG message.
int ast_is_logger_initialized(void)
Test if logger is initialized.
Definition: logger.c:1929
#define VERBOSE_PREFIX_2
void ast_init_logger_for_socket_console(void)
load logger.conf configuration for console socket connections
Definition: logger.c:700
const char * ast_logger_get_dateformat(void)
Get the logger configured date format.
Definition: logger.c:2661
#define VERBOSE_PREFIX_4
#define __LOG_VERBOSE
#define VERBOSE_PREFIX_1
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
int ast_verb_console_get(void)
Get this thread's console verbosity level.
Definition: logger.c:2407
#define VERBOSE_MAGIC2LEVEL(x)
#define VERBOSE_HASMAGIC(x)
Security Event Reporting API.
int ast_security_stasis_init(void)
initializes stasis topic/event types for ast_security_topic and ast_security_event_type
I/O Management (derived from Cheops-NG)
int ast_get_termcols(int fd)
Columns of Terminal.
Definition: io.c:373
int ast_sd_notify(const char *state)
a wrapper for sd_notify(): notify systemd of any state changes.
Definition: io.c:392
int ast_sd_get_fd_un(int type, const char *path)
Find a listening AF_LOCAL file descriptor provided by socket activation.
Definition: io.c:454
Asterisk JSON abstraction layer.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
int ast_json_init(void)
Initialize the JSON library.
Definition: json.c:705
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#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:291
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#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:333
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:415
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:2524
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:1739
Asterisk locking-related definitions:
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
static char * levels[NUMLOGLEVELS]
Logging channels used in the Asterisk logging system.
Definition: logger.c:213
static char hostname[MAXHOSTNAMELEN]
Definition: logger.c:119
#define WEXITSTATUS(status)
#define WIFEXITED(status)
int errno
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
Definition: main/utils.c:590
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
An in-memory media cache.
int ast_media_cache_init(void)
Initialize the media cache.
Definition: media_cache.c:671
Asterisk module definitions.
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
Definition: loader.c:1562
Asterisk MWI API.
int mwi_init(void)
Initialize the mwi core.
Definition: mwi.c:507
Wrapper for network related headers, masking differences between various operating systems....
#define MAXHOSTNAMELEN
Definition: network.h:69
Options provided by main asterisk program.
#define ast_opt_dump_core
Definition: options.h:119
#define ast_opt_remote
Definition: options.h:112
int ast_language_is_prefix
The following variable controls the layout of localized sound files. If 0, use the historical layout ...
Definition: file.c:67
#define MAX_PJ_LOG_MAX_LEVEL
Definition: options.h:140
#define ast_opt_exec
Definition: options.h:113
#define ast_opt_reconnect
Definition: options.h:123
#define DEFAULT_PJPROJECT_CACHE_POOLS
Definition: options.h:177
#define ast_opt_console
Definition: options.h:109
#define ast_opt_hide_connect
Definition: options.h:132
#define ast_opt_mute
Definition: options.h:127