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