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