1999-11-15 04:57:28 +00:00
/*
2005-09-14 20:46:50 +00:00
* Asterisk - - An open source telephony toolkit .
1999-11-15 04:57:28 +00:00
*
2008-01-24 17:24:08 +00:00
* Copyright ( C ) 1999 - 2008 , Digium , Inc .
1999-11-15 04:57:28 +00:00
*
2004-08-27 03:28:32 +00:00
* Mark Spencer < markster @ digium . com >
1999-11-15 04:57:28 +00:00
*
2005-09-14 20:46:50 +00:00
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
* the project provides a web site , mailing lists and IRC
* channels for your use .
*
1999-11-15 04:57:28 +00:00
* This program is free software , distributed under the terms of
2005-09-14 20:46:50 +00:00
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree .
*/
2005-10-24 20:12:06 +00:00
/* Doxygenified Copyright Header */
/*!
* \ mainpage Asterisk - - An Open Source Telephony Toolkit
*
2005-11-14 19:00:38 +00:00
* \ par Developer Documentation for Asterisk
2008-12-09 22:38:41 +00:00
*
2005-11-14 19:00:38 +00:00
* This is the main developer documentation for Asterisk . It is
2008-12-09 22:38:41 +00:00
* generated by running " make progdocs " from the Asterisk source tree .
*
* In addition to the information available on the Asterisk source code ,
* please see the appendices for information on coding guidelines ,
* release management , commit policies , and more .
*
2005-11-14 19:00:38 +00:00
* \ par Additional documentation
2008-07-25 14:57:11 +00:00
* \ arg \ ref Licensing
2005-10-24 20:12:06 +00:00
* \ arg \ ref DevDoc
* \ arg \ ref ConfigFiles
*
2008-12-09 22:38:41 +00:00
* \ section copyright Copyright and Author
2005-10-24 20:12:06 +00:00
*
2009-02-25 12:45:30 +00:00
* Copyright ( C ) 1999 - 2009 , Digium , Inc .
2008-12-09 22:38:41 +00:00
* Asterisk is a < a href = " http://www.digium.com/en/company/view-policy.php?id=Trademark-Policy " > registered trademark < / a >
* of < a href = " http://www.digium.com " > Digium , Inc < / a > .
2005-10-24 20:12:06 +00:00
*
* \ author Mark Spencer < markster @ digium . com >
* Also see \ ref AstCREDITS
*
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
2008-12-09 22:38:41 +00:00
* the project provides a web site , mailing lists , and IRC
2005-10-24 20:12:06 +00:00
* channels for your use .
*/
/*! \file
\ brief Top level source file for Asterisk - the Open Source PBX . Implementation
of PBX core functions and CLI interface .
1999-11-15 04:57:28 +00:00
*/
2006-06-07 18:54:56 +00:00
# include "asterisk.h"
ASTERISK_FILE_VERSION ( __FILE__ , " $Revision$ " )
2007-11-20 22:18:21 +00:00
# include "asterisk/_private.h"
2007-04-09 03:04:07 +00:00
# undef sched_setscheduler
# undef setpriority
2005-04-29 17:24:58 +00:00
# include <sys/time.h>
2005-04-22 13:11:34 +00:00
# include <fcntl.h>
# include <signal.h>
# include <sched.h>
# include <sys/un.h>
# include <sys/wait.h>
# include <ctype.h>
# include <sys/resource.h>
# include <grp.h>
# include <pwd.h>
# include <sys/stat.h>
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
# include <sys/sysinfo.h>
2008-12-16 20:08:34 +00:00
# elif defined(HAVE_SYSCTL)
# include <sys/param.h>
# include <sys/sysctl.h>
2009-01-14 19:36:57 +00:00
# if !defined(__OpenBSD__)
# include <sys/vmmeter.h>
# if defined(__FreeBSD__)
# include <vm/vm_param.h>
# endif
# endif
2009-01-12 14:35:09 +00:00
# if defined(HAVE_SWAPCTL)
2008-12-16 20:08:34 +00:00
# include <sys/swap.h>
2007-04-11 20:59:08 +00:00
# endif
2009-01-12 14:35:09 +00:00
# endif
2005-06-06 20:27:51 +00:00
# include <regex.h>
2005-04-22 13:11:34 +00:00
2006-03-02 22:27:50 +00:00
# if defined(SOLARIS)
2006-06-07 18:54:56 +00:00
int daemon ( int , int ) ; /* defined in libresolv of all places */
2007-09-12 16:24:45 +00:00
# include <sys/loadavg.h>
2006-03-02 22:27:50 +00:00
# endif
2005-04-22 13:11:34 +00:00
2008-04-08 17:00:55 +00:00
# ifdef linux
# include <sys/prctl.h>
# ifdef HAVE_CAP
# include <sys/capability.h>
# endif /* HAVE_CAP */
# endif /* linux */
2007-12-18 10:24:58 +00:00
# include "asterisk/paths.h" /* we define here the variables so better agree on the prototype */
2007-11-17 14:11:53 +00:00
# include "asterisk/network.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/cli.h"
# include "asterisk/channel.h"
2008-01-23 23:09:11 +00:00
# include "asterisk/features.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/ulaw.h"
# include "asterisk/alaw.h"
# include "asterisk/callerid.h"
# include "asterisk/image.h"
# include "asterisk/tdd.h"
# include "asterisk/term.h"
# include "asterisk/manager.h"
2005-06-03 01:42:31 +00:00
# include "asterisk/cdr.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/pbx.h"
# include "asterisk/enum.h"
# include "asterisk/rtp.h"
2006-03-25 23:50:09 +00:00
# include "asterisk/http.h"
2006-01-12 17:14:58 +00:00
# include "asterisk/udptl.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/app.h"
# include "asterisk/lock.h"
# include "asterisk/utils.h"
# include "asterisk/file.h"
# include "asterisk/io.h"
2003-02-06 06:15:25 +00:00
# include "editline/histedit.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/config.h"
2008-02-26 20:33:08 +00:00
# include "asterisk/ast_version.h"
2005-06-06 20:27:51 +00:00
# include "asterisk/linkedlists.h"
2005-07-08 21:14:34 +00:00
# include "asterisk/devicestate.h"
2007-06-05 15:54:36 +00:00
# include "asterisk/module.h"
2008-03-05 16:23:44 +00:00
# include "asterisk/dsp.h"
2008-10-30 16:49:02 +00:00
# include "asterisk/buildinfo.h"
2008-11-10 13:53:23 +00:00
# include "asterisk/xmldoc.h"
2005-06-06 03:04:58 +00:00
2005-10-24 20:12:06 +00:00
# include "asterisk/doxyref.h" /* Doxygen documentation */
2006-08-21 02:11:39 +00:00
# include "../defaults.h"
2004-04-28 13:53:01 +00:00
2004-12-14 23:36:30 +00:00
# ifndef AF_LOCAL
# define AF_LOCAL AF_UNIX
# define PF_LOCAL PF_UNIX
# endif
2001-05-09 03:11:22 +00:00
# define AST_MAX_CONNECTS 128
# define NUM_MSGS 64
2005-11-14 19:00:38 +00:00
/*! \brief Welcome message when starting a CLI interface */
2005-12-23 03:04:38 +00:00
# define WELCOME_MESSAGE \
2008-01-24 17:24:08 +00:00
ast_verbose ( " Asterisk %s, Copyright (C) 1999 - 2008 Digium, Inc. and others. \n " \
2007-02-13 06:02:57 +00:00
" Created by Mark Spencer <markster@digium.com> \n " \
" Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details. \n " \
" This is free software, with components licensed under the GNU General Public \n " \
" License version 2 and other licenses; you are welcome to redistribute it under \n " \
" certain conditions. Type 'core show license' for details. \n " \
2008-02-12 15:39:44 +00:00
" ========================================================================= \n " , ast_get_version ( ) ) \
2004-06-25 21:14:03 +00:00
2006-10-30 16:33:02 +00:00
/*! \defgroup main_options Main Configuration Options
2007-07-23 14:32:04 +00:00
* \ brief Main configuration options from asterisk . conf or OS command line on starting Asterisk .
* \ arg \ ref Config_ast " asterisk.conf "
* \ note Some of them can be changed in the CLI
2005-11-14 19:00:38 +00:00
*/
/*! @{ */
2005-12-04 20:40:46 +00:00
2006-03-14 16:57:35 +00:00
struct ast_flags ast_options = { AST_DEFAULT_OPTIONS } ;
2008-06-03 22:05:16 +00:00
struct ast_flags ast_compat = { 7 } ;
2005-12-04 20:40:46 +00:00
2006-12-27 22:14:33 +00:00
int option_verbose ; /*!< Verbosity level */
int option_debug ; /*!< Debug level */
double option_maxload ; /*!< Max load avg on system */
int option_maxcalls ; /*!< Max number of active calls */
2007-02-14 20:22:20 +00:00
int option_maxfiles ; /*!< Max number of open file handles (files, sockets) */
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
long option_minmemfree ; /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
2007-04-11 20:59:08 +00:00
# endif
2005-11-14 19:00:38 +00:00
/*! @} */
2008-06-10 12:48:50 +00:00
struct ast_eid g_eid ;
2007-12-18 09:26:03 +00:00
/* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
char record_cache_dir [ AST_CACHE_DIR_LEN ] = DEFAULT_TMP_DIR ;
1999-12-19 22:38:55 +00:00
2005-10-24 20:12:06 +00:00
static int ast_socket = - 1 ; /*!< UNIX Socket for allowing remote control */
static int ast_consock = - 1 ; /*!< UNIX Socket for controlling another asterisk */
2006-05-08 12:32:44 +00:00
pid_t ast_mainpid ;
2001-05-09 03:11:22 +00:00
struct console {
2005-10-24 20:12:06 +00:00
int fd ; /*!< File descriptor */
int p [ 2 ] ; /*!< Pipe */
pthread_t t ; /*!< Thread of handler */
2006-05-26 19:48:17 +00:00
int mute ; /*!< Is the console muted for logs */
2008-12-01 18:52:14 +00:00
int uid ; /*!< Remote user ID. */
int gid ; /*!< Remote group ID. */
2008-05-29 21:30:37 +00:00
int levels [ NUMLOGLEVELS ] ; /*!< Which log levels are enabled for the console */
2001-05-09 03:11:22 +00:00
} ;
2006-01-24 20:27:09 +00:00
struct ast_atexit {
2003-08-07 03:48:00 +00:00
void ( * func ) ( void ) ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_ENTRY ( ast_atexit ) list ;
2006-01-24 20:27:09 +00:00
} ;
2005-10-24 20:12:06 +00:00
2007-06-18 16:37:14 +00:00
static AST_RWLIST_HEAD_STATIC ( atexits , ast_atexit ) ;
2003-08-07 03:48:00 +00:00
2007-07-18 19:47:20 +00:00
struct timeval ast_startuptime ;
struct timeval ast_lastreloadtime ;
2003-05-02 15:37:34 +00:00
2006-12-27 22:14:33 +00:00
static History * el_hist ;
static EditLine * el ;
2003-02-06 06:15:25 +00:00
static char * remotehostname ;
2001-05-09 03:11:22 +00:00
struct console consoles [ AST_MAX_CONNECTS ] ;
2000-01-09 19:58:18 +00:00
char defaultlanguage [ MAX_LANGUAGE ] = DEFAULT_LANGUAGE ;
2003-02-06 06:15:25 +00:00
static int ast_el_add_history ( char * ) ;
static int ast_el_read_history ( char * ) ;
static int ast_el_write_history ( char * ) ;
2007-12-20 09:55:05 +00:00
struct _cfg_paths {
char config_dir [ PATH_MAX ] ;
char module_dir [ PATH_MAX ] ;
char spool_dir [ PATH_MAX ] ;
char monitor_dir [ PATH_MAX ] ;
char var_dir [ PATH_MAX ] ;
char data_dir [ PATH_MAX ] ;
char log_dir [ PATH_MAX ] ;
char agi_dir [ PATH_MAX ] ;
char run_dir [ PATH_MAX ] ;
char key_dir [ PATH_MAX ] ;
char config_file [ PATH_MAX ] ;
char db_path [ PATH_MAX ] ;
char pid_path [ PATH_MAX ] ;
char socket_path [ PATH_MAX ] ;
char run_user [ PATH_MAX ] ;
char run_group [ PATH_MAX ] ;
char system_name [ 128 ] ;
} ;
static struct _cfg_paths cfg_paths ;
const char * ast_config_AST_CONFIG_DIR = cfg_paths . config_dir ;
const char * ast_config_AST_CONFIG_FILE = cfg_paths . config_file ;
const char * ast_config_AST_MODULE_DIR = cfg_paths . module_dir ;
const char * ast_config_AST_SPOOL_DIR = cfg_paths . spool_dir ;
const char * ast_config_AST_MONITOR_DIR = cfg_paths . monitor_dir ;
const char * ast_config_AST_VAR_DIR = cfg_paths . var_dir ;
const char * ast_config_AST_DATA_DIR = cfg_paths . data_dir ;
const char * ast_config_AST_LOG_DIR = cfg_paths . log_dir ;
const char * ast_config_AST_AGI_DIR = cfg_paths . agi_dir ;
const char * ast_config_AST_KEY_DIR = cfg_paths . key_dir ;
const char * ast_config_AST_RUN_DIR = cfg_paths . run_dir ;
const char * ast_config_AST_DB = cfg_paths . db_path ;
const char * ast_config_AST_PID = cfg_paths . pid_path ;
const char * ast_config_AST_SOCKET = cfg_paths . socket_path ;
const char * ast_config_AST_RUN_USER = cfg_paths . run_user ;
const char * ast_config_AST_RUN_GROUP = cfg_paths . run_group ;
const char * ast_config_AST_SYSTEM_NAME = cfg_paths . system_name ;
static char ast_config_AST_CTL_PERMISSIONS [ PATH_MAX ] ;
static char ast_config_AST_CTL_OWNER [ PATH_MAX ] = " \0 " ;
static char ast_config_AST_CTL_GROUP [ PATH_MAX ] = " \0 " ;
static char ast_config_AST_CTL [ PATH_MAX ] = " asterisk.ctl " ;
2003-02-06 06:15:25 +00:00
2004-02-23 03:43:21 +00:00
static char * _argv [ 256 ] ;
2006-12-27 22:14:33 +00:00
static int shuttingdown ;
static int restartnow ;
2004-03-15 07:51:22 +00:00
static pthread_t consolethread = AST_PTHREADT_NULL ;
2007-12-18 23:06:05 +00:00
static int canary_pid = 0 ;
static char canary_filename [ 128 ] ;
2009-02-24 20:06:48 +00:00
static int canary_pipe = - 1 ;
2004-02-23 03:43:21 +00:00
2006-01-10 00:55:45 +00:00
static char randompool [ 256 ] ;
2007-02-23 23:25:22 +00:00
static int sig_alert_pipe [ 2 ] = { - 1 , - 1 } ;
static struct {
unsigned int need_reload : 1 ;
unsigned int need_quit : 1 ;
} sig_flags ;
2007-01-30 17:23:56 +00:00
2005-06-07 16:07:06 +00:00
# if !defined(LOW_MEMORY)
2005-06-06 20:27:51 +00:00
struct file_version {
2007-06-18 16:37:14 +00:00
AST_RWLIST_ENTRY ( file_version ) list ;
2005-06-06 21:09:59 +00:00
const char * file ;
char * version ;
2005-06-06 20:27:51 +00:00
} ;
2007-06-18 16:37:14 +00:00
static AST_RWLIST_HEAD_STATIC ( file_versions , file_version ) ;
2005-06-06 20:27:51 +00:00
void ast_register_file_version ( const char * file , const char * version )
{
struct file_version * new ;
2005-06-06 21:09:59 +00:00
char * work ;
size_t version_length ;
2005-06-06 20:27:51 +00:00
2005-06-06 21:09:59 +00:00
work = ast_strdupa ( version ) ;
work = ast_strip ( ast_strip_quoted ( work , " $ " , " $ " ) ) ;
version_length = strlen ( work ) + 1 ;
2006-02-14 22:28:01 +00:00
if ( ! ( new = ast_calloc ( 1 , sizeof ( * new ) + version_length ) ) )
2005-06-06 20:27:51 +00:00
return ;
new - > file = file ;
2005-06-06 21:09:59 +00:00
new - > version = ( char * ) new + sizeof ( * new ) ;
memcpy ( new - > version , work , version_length ) ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & file_versions ) ;
AST_RWLIST_INSERT_HEAD ( & file_versions , new , list ) ;
AST_RWLIST_UNLOCK ( & file_versions ) ;
2005-06-06 20:27:51 +00:00
}
void ast_unregister_file_version ( const char * file )
{
struct file_version * find ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & file_versions ) ;
AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & file_versions , find , list ) {
2005-06-06 20:27:51 +00:00
if ( ! strcasecmp ( find - > file , file ) ) {
2007-11-08 05:28:47 +00:00
AST_RWLIST_REMOVE_CURRENT ( list ) ;
2005-06-06 20:27:51 +00:00
break ;
}
}
2007-06-18 16:37:14 +00:00
AST_RWLIST_TRAVERSE_SAFE_END ;
AST_RWLIST_UNLOCK ( & file_versions ) ;
2007-06-08 15:32:46 +00:00
2005-06-06 21:09:59 +00:00
if ( find )
2007-06-06 21:20:11 +00:00
ast_free ( find ) ;
2005-06-06 20:27:51 +00:00
}
2008-12-10 17:09:15 +00:00
char * ast_complete_source_filename ( const char * partial , int n )
{
struct file_version * find ;
size_t len = strlen ( partial ) ;
int count = 0 ;
char * res = NULL ;
AST_RWLIST_RDLOCK ( & file_versions ) ;
AST_RWLIST_TRAVERSE ( & file_versions , find , list ) {
if ( ! strncasecmp ( find - > file , partial , len ) & & + + count > n ) {
res = ast_strdup ( find - > file ) ;
break ;
}
}
AST_RWLIST_UNLOCK ( & file_versions ) ;
return res ;
}
2007-11-27 21:04:29 +00:00
/*! \brief Find version for given module name */
const char * ast_file_version_find ( const char * file )
{
struct file_version * iterator ;
AST_RWLIST_WRLOCK ( & file_versions ) ;
AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & file_versions , iterator , list ) {
if ( ! strcasecmp ( iterator - > file , file ) )
break ;
}
AST_RWLIST_TRAVERSE_SAFE_END ;
AST_RWLIST_UNLOCK ( & file_versions ) ;
if ( iterator )
return iterator - > version ;
return NULL ;
}
2006-04-12 20:40:46 +00:00
struct thread_list_t {
2007-06-18 16:37:14 +00:00
AST_RWLIST_ENTRY ( thread_list_t ) list ;
2006-04-12 20:40:46 +00:00
char * name ;
pthread_t id ;
} ;
2007-06-18 16:37:14 +00:00
static AST_RWLIST_HEAD_STATIC ( thread_list , thread_list_t ) ;
2006-04-12 20:40:46 +00:00
void ast_register_thread ( char * name )
{
struct thread_list_t * new = ast_calloc ( 1 , sizeof ( * new ) ) ;
if ( ! new )
return ;
new - > id = pthread_self ( ) ;
2006-10-04 19:51:38 +00:00
new - > name = name ; /* steal the allocated memory for the thread name */
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & thread_list ) ;
AST_RWLIST_INSERT_HEAD ( & thread_list , new , list ) ;
AST_RWLIST_UNLOCK ( & thread_list ) ;
2006-04-12 20:40:46 +00:00
}
void ast_unregister_thread ( void * id )
{
struct thread_list_t * x ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & thread_list ) ;
AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & thread_list , x , list ) {
2006-10-04 19:51:38 +00:00
if ( ( void * ) x - > id = = id ) {
2007-11-08 05:28:47 +00:00
AST_RWLIST_REMOVE_CURRENT ( list ) ;
2006-04-12 20:40:46 +00:00
break ;
}
}
2007-06-18 16:37:14 +00:00
AST_RWLIST_TRAVERSE_SAFE_END ;
AST_RWLIST_UNLOCK ( & thread_list ) ;
2006-04-12 20:40:46 +00:00
if ( x ) {
2007-06-06 21:20:11 +00:00
ast_free ( x - > name ) ;
ast_free ( x ) ;
2006-04-12 20:40:46 +00:00
}
}
2007-02-14 20:22:20 +00:00
/*! \brief Give an overview of core settings */
2007-10-11 19:03:06 +00:00
static char * handle_show_settings ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2007-02-14 20:22:20 +00:00
{
char buf [ BUFSIZ ] ;
2007-07-18 19:47:20 +00:00
struct ast_tm tm ;
2008-06-10 12:48:50 +00:00
char eid_str [ 128 ] ;
2007-02-14 20:22:20 +00:00
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show settings " ;
e - > usage = " Usage: core show settings \n "
" Show core misc settings " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-06-10 12:48:50 +00:00
ast_eid_to_str ( eid_str , sizeof ( eid_str ) , & g_eid ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n PBX Core settings \n " ) ;
ast_cli ( a - > fd , " ----------------- \n " ) ;
Now that the version.h file was getting properly regenerated every time the svn
revision changed, every module that used the version was getting rebuilt after
every svn update. This severly annoyed me pretty quickly, so I have improved
the situation.
Now, instead of generating version.h, main/version.c is generated. version.c
includes the version information, as well as a couple of API calls for modules
to retrieve the version. So now, only version.c will get rebuilt, and the main
asterisk binary relinked, which is must faster than rebuilding http.c, manager.c,
asterisk.c, relinking the asterisk binary, chan_sip.c, func_version.c, res_agi ...
The only minor change in behavior here is that the version information reported by
chan_sip, for example, is the version of the Asterisk core, and not necessarily the
Asterisk version that the chan_sip module came from.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@96717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-01-05 22:09:06 +00:00
ast_cli ( a - > fd , " Version: %s \n " , ast_get_version ( ) ) ;
2008-05-22 13:40:52 +00:00
ast_cli ( a - > fd , " Build Options: %s \n " , S_OR ( AST_BUILDOPTS , " (none) " ) ) ;
2007-02-14 20:22:20 +00:00
if ( option_maxcalls )
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Maximum calls: %d (Current %d) \n " , option_maxcalls , ast_active_channels ( ) ) ;
2007-02-14 20:22:20 +00:00
else
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Maximum calls: Not set \n " ) ;
2007-02-14 20:22:20 +00:00
if ( option_maxfiles )
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Maximum open file handles: %d \n " , option_maxfiles ) ;
2007-02-14 20:22:20 +00:00
else
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Maximum open file handles: Not set \n " ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Verbosity: %d \n " , option_verbose ) ;
ast_cli ( a - > fd , " Debug level: %d \n " , option_debug ) ;
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Maximum load average: %lf \n " , option_maxload ) ;
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Minimum free memory: %ld MB \n " , option_minmemfree ) ;
2007-04-11 20:59:08 +00:00
# endif
2007-06-14 22:09:20 +00:00
if ( ast_localtime ( & ast_startuptime , & tm , NULL ) ) {
2007-07-18 19:47:20 +00:00
ast_strftime ( buf , sizeof ( buf ) , " %H:%M:%S " , & tm ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Startup time: %s \n " , buf ) ;
2007-02-14 20:22:20 +00:00
}
2007-06-14 22:09:20 +00:00
if ( ast_localtime ( & ast_lastreloadtime , & tm , NULL ) ) {
2007-07-18 19:47:20 +00:00
ast_strftime ( buf , sizeof ( buf ) , " %H:%M:%S " , & tm ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Last reload time: %s \n " , buf ) ;
2007-02-14 20:22:20 +00:00
}
2007-10-11 19:03:06 +00:00
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 ) ;
ast_cli ( a - > fd , " System name: %s \n " , ast_config_AST_SYSTEM_NAME ) ;
2008-06-10 12:48:50 +00:00
ast_cli ( a - > fd , " Entity ID: %s \n " , eid_str ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Default language: %s \n " , defaultlanguage ) ;
ast_cli ( a - > fd , " Language prefix: %s \n " , ast_language_is_prefix ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " User name and group: %s/%s \n " , ast_config_AST_RUN_USER , ast_config_AST_RUN_GROUP ) ;
ast_cli ( a - > fd , " Executable includes: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_EXEC_INCLUDES ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Transcode via SLIN: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_TRANSCODE_VIA_SLIN ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Internal timing: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_INTERNAL_TIMING ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Transmit silence during rec: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_INTERNAL_TIMING ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " \n * Subsystems \n " ) ;
ast_cli ( a - > fd , " ------------- \n " ) ;
ast_cli ( a - > fd , " Manager (AMI): %s \n " , check_manager_enabled ( ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Web Manager (AMI/HTTP): %s \n " , check_webmanager_enabled ( ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Call data records: %s \n " , check_cdr_enabled ( ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Realtime Architecture (ARA): %s \n " , ast_realtime_enabled ( ) ? " Enabled " : " Disabled " ) ;
2007-02-14 20:22:20 +00:00
/*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n * Directories \n " ) ;
ast_cli ( a - > fd , " ------------- \n " ) ;
ast_cli ( a - > fd , " Configuration file: %s \n " , ast_config_AST_CONFIG_FILE ) ;
ast_cli ( a - > fd , " Configuration directory: %s \n " , ast_config_AST_CONFIG_DIR ) ;
ast_cli ( a - > fd , " Module directory: %s \n " , ast_config_AST_MODULE_DIR ) ;
ast_cli ( a - > fd , " Spool directory: %s \n " , ast_config_AST_SPOOL_DIR ) ;
ast_cli ( a - > fd , " Log directory: %s \n " , ast_config_AST_LOG_DIR ) ;
ast_cli ( a - > fd , " \n \n " ) ;
return CLI_SUCCESS ;
2007-02-14 20:22:20 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_show_threads ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2006-04-12 20:40:46 +00:00
{
int count = 0 ;
struct thread_list_t * cur ;
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show threads " ;
e - > usage =
" Usage: core show threads \n "
" List threads currently active in the system. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2006-04-12 20:40:46 +00:00
2007-06-18 16:37:14 +00:00
AST_RWLIST_RDLOCK ( & thread_list ) ;
AST_RWLIST_TRAVERSE ( & thread_list , cur , list ) {
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %p %s \n " , ( void * ) cur - > id , cur - > name ) ;
2006-04-12 20:40:46 +00:00
count + + ;
}
2007-06-18 16:37:14 +00:00
AST_RWLIST_UNLOCK ( & thread_list ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %d threads listed. \n " , count ) ;
return CLI_SUCCESS ;
2006-04-12 20:40:46 +00:00
}
2008-12-16 20:08:34 +00:00
# if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
/*
* swapmode is rewritten by Tobias Weingartner < weingart @ openbsd . org >
* to be based on the new swapctl ( 2 ) system call .
*/
static int swapmode ( int * used , int * total )
{
struct swapent * swdev ;
int nswap , rnswap , i ;
nswap = swapctl ( SWAP_NSWAP , 0 , 0 ) ;
if ( nswap = = 0 )
return 0 ;
swdev = ast_calloc ( nswap , sizeof ( * swdev ) ) ;
if ( swdev = = NULL )
return 0 ;
rnswap = swapctl ( SWAP_STATS , swdev , nswap ) ;
if ( rnswap = = - 1 ) {
ast_free ( swdev ) ;
return 0 ;
}
/* if rnswap != nswap, then what? */
/* Total things up */
* total = * used = 0 ;
for ( i = 0 ; i < nswap ; i + + ) {
if ( swdev [ i ] . se_flags & SWF_ENABLE ) {
* used + = ( swdev [ i ] . se_inuse / ( 1024 / DEV_BSIZE ) ) ;
* total + = ( swdev [ i ] . se_nblks / ( 1024 / DEV_BSIZE ) ) ;
}
}
ast_free ( swdev ) ;
return 1 ;
}
2008-12-16 20:49:25 +00:00
# elif defined(HAVE_SYSCTL) && !defined(HAVE_SYSINFO)
2008-12-16 20:08:34 +00:00
static int swapmode ( int * used , int * total )
{
2009-01-19 20:14:27 +00:00
* used = * total = 0 ;
2008-12-16 20:08:34 +00:00
return 1 ;
}
# endif
2009-02-21 14:37:04 +00:00
# if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2007-04-11 19:11:32 +00:00
/*! \brief Give an overview of system statistics */
2007-10-11 19:03:06 +00:00
static char * handle_show_sysinfo ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2007-04-11 19:11:32 +00:00
{
2008-12-16 20:08:34 +00:00
int64_t physmem , freeram ;
2009-01-14 19:36:57 +00:00
int totalswap = 0 , freeswap = 0 , nprocs = 0 ;
2008-12-16 20:08:34 +00:00
long uptime = 0 ;
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
struct sysinfo sys_info ;
2008-12-16 20:49:25 +00:00
sysinfo ( & sys_info ) ;
2008-12-16 20:08:34 +00:00
uptime = sys_info . uptime / 3600 ;
physmem = sys_info . totalram * sys_info . mem_unit ;
freeram = ( sys_info . freeram * sys_info . mem_unit ) / 1024 ;
totalswap = ( sys_info . totalswap * sys_info . mem_unit ) / 1024 ;
freeswap = ( sys_info . freeswap * sys_info . mem_unit ) / 1024 ;
2008-12-16 20:49:25 +00:00
nprocs = sys_info . procs ;
2008-12-16 20:08:34 +00:00
# elif defined(HAVE_SYSCTL)
static int pageshift ;
struct vmtotal vmtotal ;
struct timeval boottime ;
time_t now ;
2009-01-14 19:36:57 +00:00
int mib [ 2 ] , pagesize , usedswap = 0 ;
2008-12-16 20:08:34 +00:00
size_t len ;
/* calculate the uptime by looking at boottime */
time ( & now ) ;
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_BOOTTIME ;
len = sizeof ( boottime ) ;
if ( sysctl ( mib , 2 , & boottime , & len , NULL , 0 ) ! = - 1 ) {
uptime = now - boottime . tv_sec ;
}
uptime = uptime / 3600 ;
/* grab total physical memory */
mib [ 0 ] = CTL_HW ;
2009-01-19 18:36:24 +00:00
# if defined(HW_PHYSMEM64)
2008-12-16 20:08:34 +00:00
mib [ 1 ] = HW_PHYSMEM64 ;
2009-01-14 19:36:57 +00:00
# else
mib [ 1 ] = HW_PHYSMEM ;
# endif
2008-12-16 20:08:34 +00:00
len = sizeof ( physmem ) ;
sysctl ( mib , 2 , & physmem , & len , NULL , 0 ) ;
pagesize = getpagesize ( ) ;
pageshift = 0 ;
while ( pagesize > 1 ) {
pageshift + + ;
pagesize > > = 1 ;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift - = 10 ;
/* grab vm totals */
mib [ 0 ] = CTL_VM ;
mib [ 1 ] = VM_METER ;
len = sizeof ( vmtotal ) ;
sysctl ( mib , 2 , & vmtotal , & len , NULL , 0 ) ;
freeram = ( vmtotal . t_free < < pageshift ) ;
/* generate swap usage and totals */
swapmode ( & usedswap , & totalswap ) ;
freeswap = ( totalswap - usedswap ) ;
/* grab number of processes */
2009-01-14 19:36:57 +00:00
# if defined(__OpenBSD__)
2008-12-16 20:08:34 +00:00
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_NPROCS ;
len = sizeof ( nprocs ) ;
sysctl ( mib , 2 , & nprocs , & len , NULL , 0 ) ;
2009-01-14 19:36:57 +00:00
# endif
2008-12-16 20:08:34 +00:00
# endif
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show sysinfo " ;
e - > usage =
" Usage: core show sysinfo \n "
" List current system information. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-12-16 20:08:34 +00:00
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n System Statistics \n " ) ;
ast_cli ( a - > fd , " ----------------- \n " ) ;
2008-12-16 20:08:34 +00:00
ast_cli ( a - > fd , " System Uptime: %ld hours \n " , uptime ) ;
ast_cli ( a - > fd , " Total RAM: %ld KiB \n " , ( long ) physmem / 1024 ) ;
ast_cli ( a - > fd , " Free RAM: %ld KiB \n " , ( long ) freeram ) ;
# if defined(HAVE_SYSINFO)
2008-07-16 21:24:18 +00:00
ast_cli ( a - > fd , " Buffer RAM: %ld KiB \n " , ( sys_info . bufferram * sys_info . mem_unit ) / 1024 ) ;
2008-12-16 20:08:34 +00:00
# endif
ast_cli ( a - > fd , " Total Swap Space: %ld KiB \n " , ( long ) totalswap ) ;
ast_cli ( a - > fd , " Free Swap Space: %ld KiB \n \n " , ( long ) freeswap ) ;
ast_cli ( a - > fd , " Number of Processes: %d \n \n " , nprocs ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2007-04-11 19:11:32 +00:00
}
2009-02-21 14:37:04 +00:00
# endif
2007-04-11 19:11:32 +00:00
2006-04-12 20:40:46 +00:00
struct profile_entry {
const char * name ;
uint64_t scale ; /* if non-zero, values are scaled by this */
int64_t mark ;
int64_t value ;
int64_t events ;
} ;
struct profile_data {
int entries ;
int max_size ;
struct profile_entry e [ 0 ] ;
} ;
static struct profile_data * prof_data ;
2006-06-08 18:03:08 +00:00
/*! \brief allocates a counter with a given name and scale.
* \ return Returns the identifier of the counter .
2006-04-12 20:40:46 +00:00
*/
int ast_add_profile ( const char * name , uint64_t scale )
{
int l = sizeof ( struct profile_data ) ;
int n = 10 ; /* default entries */
if ( prof_data = = NULL ) {
prof_data = ast_calloc ( 1 , l + n * sizeof ( struct profile_entry ) ) ;
if ( prof_data = = NULL )
return - 1 ;
prof_data - > entries = 0 ;
prof_data - > max_size = n ;
}
if ( prof_data - > entries > = prof_data - > max_size ) {
void * p ;
n = prof_data - > max_size + 20 ;
p = ast_realloc ( prof_data , l + n * sizeof ( struct profile_entry ) ) ;
if ( p = = NULL )
return - 1 ;
prof_data = p ;
prof_data - > max_size = n ;
}
n = prof_data - > entries + + ;
prof_data - > e [ n ] . name = ast_strdup ( name ) ;
prof_data - > e [ n ] . value = 0 ;
prof_data - > e [ n ] . events = 0 ;
prof_data - > e [ n ] . mark = 0 ;
prof_data - > e [ n ] . scale = scale ;
return n ;
}
int64_t ast_profile ( int i , int64_t delta )
{
if ( ! prof_data | | i < 0 | | i > prof_data - > entries ) /* invalid index */
return 0 ;
if ( prof_data - > e [ i ] . scale > 1 )
delta / = prof_data - > e [ i ] . scale ;
prof_data - > e [ i ] . value + = delta ;
prof_data - > e [ i ] . events + + ;
return prof_data - > e [ i ] . value ;
}
2008-06-19 16:08:29 +00:00
/* The RDTSC instruction was introduced on the Pentium processor and is not
* implemented on certain clones , like the Cyrix 586. Hence , the previous
* expectation of __i386__ was in error . */
# if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
2006-04-12 20:40:46 +00:00
# if defined(__FreeBSD__)
# include <machine/cpufunc.h>
# elif defined(linux)
2006-08-22 05:34:44 +00:00
static __inline uint64_t
2006-04-12 20:40:46 +00:00
rdtsc ( void )
{
uint64_t rv ;
__asm __volatile ( " .byte 0x0f, 0x31 " : " =A " ( rv ) ) ;
return ( rv ) ;
}
# endif
# else /* supply a dummy function on other platforms */
2006-08-22 05:34:44 +00:00
static __inline uint64_t
2006-04-12 20:40:46 +00:00
rdtsc ( void )
{
return 0 ;
}
# endif
int64_t ast_mark ( int i , int startstop )
{
if ( ! prof_data | | i < 0 | | i > prof_data - > entries ) /* invalid index */
return 0 ;
if ( startstop = = 1 )
prof_data - > e [ i ] . mark = rdtsc ( ) ;
else {
prof_data - > e [ i ] . mark = ( rdtsc ( ) - prof_data - > e [ i ] . mark ) ;
if ( prof_data - > e [ i ] . scale > 1 )
prof_data - > e [ i ] . mark / = prof_data - > e [ i ] . scale ;
prof_data - > e [ i ] . value + = prof_data - > e [ i ] . mark ;
prof_data - > e [ i ] . events + + ;
}
return prof_data - > e [ i ] . mark ;
}
2007-10-11 19:03:06 +00:00
# define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
max = prof_data - > entries ; \
if ( a - > argc > 3 ) { /* specific entries */ \
if ( isdigit ( a - > argv [ 3 ] [ 0 ] ) ) { \
min = atoi ( a - > argv [ 3 ] ) ; \
if ( a - > argc = = 5 & & strcmp ( a - > argv [ 4 ] , " - " ) ) \
max = atoi ( a - > argv [ 4 ] ) ; \
} else \
search = a - > argv [ 3 ] ; \
} \
if ( max > prof_data - > entries ) \
max = prof_data - > entries ;
static char * handle_show_profile ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2006-09-18 19:54:18 +00:00
{
int i , min , max ;
char * search = NULL ;
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show profile " ;
e - > usage = " Usage: core show profile \n "
" show profile information " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2006-09-18 19:54:18 +00:00
if ( prof_data = = NULL )
return 0 ;
2007-10-11 19:03:06 +00:00
DEFINE_PROFILE_MIN_MAX_VALUES ;
ast_cli ( a - > fd , " profile values (%d, allocated %d) \n ------------------- \n " ,
2006-09-18 19:54:18 +00:00
prof_data - > entries , prof_data - > max_size ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %6s %8s %10s %12s %12s %s \n " , " ID " , " Scale " , " Events " ,
2006-09-18 19:54:18 +00:00
" Value " , " Average " , " Name " ) ;
for ( i = min ; i < max ; i + + ) {
2008-08-10 19:35:50 +00:00
struct profile_entry * entry = & prof_data - > e [ i ] ;
2008-08-10 20:23:50 +00:00
if ( ! search | | strstr ( entry - > name , search ) )
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %6d: [%8ld] %10ld %12lld %12lld %s \n " ,
2006-09-18 19:54:18 +00:00
i ,
2008-08-10 19:35:50 +00:00
( long ) entry - > scale ,
( long ) entry - > events , ( long long ) entry - > value ,
( long long ) ( entry - > events ? entry - > value / entry - > events : entry - > value ) ,
entry - > name ) ;
2006-09-18 19:54:18 +00:00
}
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2006-09-18 19:54:18 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_clear_profile ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
int i , min , max ;
char * search = NULL ;
switch ( cmd ) {
case CLI_INIT :
e - > command = " core clear profile " ;
e - > usage = " Usage: core clear profile \n "
" clear profile information " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
if ( prof_data = = NULL )
return 0 ;
DEFINE_PROFILE_MIN_MAX_VALUES ;
for ( i = min ; i < max ; i + + ) {
if ( ! search | | strstr ( prof_data - > e [ i ] . name , search ) ) {
prof_data - > e [ i ] . value = 0 ;
prof_data - > e [ i ] . events = 0 ;
}
}
return CLI_SUCCESS ;
}
# undef DEFINE_PROFILE_MIN_MAX_VALUES
2005-06-06 20:27:51 +00:00
2006-06-08 18:03:08 +00:00
/*! \brief CLI command to list module versions */
2007-10-11 19:03:06 +00:00
static char * handle_show_version_files ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2005-06-06 20:27:51 +00:00
{
2005-07-25 22:19:13 +00:00
# define FORMAT "%-25.25s %-40.40s\n"
2005-06-06 20:27:51 +00:00
struct file_version * iterator ;
2005-06-06 21:09:59 +00:00
regex_t regexbuf ;
int havepattern = 0 ;
2005-06-06 22:39:32 +00:00
int havename = 0 ;
2005-08-22 18:45:41 +00:00
int count_files = 0 ;
2007-10-11 19:03:06 +00:00
char * ret = NULL ;
int matchlen , which = 0 ;
struct file_version * find ;
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show file version [like] " ;
e - > usage =
" Usage: core show file version [like <pattern>] \n "
" Lists the revision numbers of the files used to build this copy of Asterisk. \n "
" Optional regular expression pattern is used to filter the file list. \n " ;
return NULL ;
case CLI_GENERATE :
matchlen = strlen ( a - > word ) ;
if ( a - > pos ! = 3 )
return NULL ;
AST_RWLIST_RDLOCK ( & file_versions ) ;
AST_RWLIST_TRAVERSE ( & file_versions , find , list ) {
if ( ! strncasecmp ( a - > word , find - > file , matchlen ) & & + + which > a - > n ) {
ret = ast_strdup ( find - > file ) ;
break ;
}
}
AST_RWLIST_UNLOCK ( & file_versions ) ;
return ret ;
}
2005-06-06 21:09:59 +00:00
2007-10-11 19:03:06 +00:00
switch ( a - > argc ) {
2007-02-26 16:38:10 +00:00
case 6 :
2007-10-11 19:03:06 +00:00
if ( ! strcasecmp ( a - > argv [ 4 ] , " like " ) ) {
if ( regcomp ( & regexbuf , a - > argv [ 5 ] , REG_EXTENDED | REG_NOSUB ) )
return CLI_SHOWUSAGE ;
2005-06-06 21:09:59 +00:00
havepattern = 1 ;
} else
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2005-06-06 21:09:59 +00:00
break ;
2007-02-26 16:38:10 +00:00
case 5 :
2005-06-06 22:39:32 +00:00
havename = 1 ;
break ;
2007-02-26 16:38:10 +00:00
case 4 :
2005-06-06 21:09:59 +00:00
break ;
default :
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2005-06-06 21:09:59 +00:00
}
2005-06-06 20:27:51 +00:00
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , FORMAT , " File " , " Revision " ) ;
ast_cli ( a - > fd , FORMAT , " ---- " , " -------- " ) ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_RDLOCK ( & file_versions ) ;
AST_RWLIST_TRAVERSE ( & file_versions , iterator , list ) {
2007-10-11 19:03:06 +00:00
if ( havename & & strcasecmp ( iterator - > file , a - > argv [ 4 ] ) )
2005-06-06 22:39:32 +00:00
continue ;
2005-06-06 21:09:59 +00:00
if ( havepattern & & regexec ( & regexbuf , iterator - > file , 0 , NULL , 0 ) )
continue ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , FORMAT , iterator - > file , iterator - > version ) ;
2005-08-22 18:45:41 +00:00
count_files + + ;
2005-06-06 22:39:32 +00:00
if ( havename )
break ;
2005-06-06 20:27:51 +00:00
}
2007-06-18 16:37:14 +00:00
AST_RWLIST_UNLOCK ( & file_versions ) ;
2005-08-22 18:45:41 +00:00
if ( ! havename ) {
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %d files listed. \n " , count_files ) ;
2005-08-22 18:45:41 +00:00
}
2005-06-06 21:09:59 +00:00
if ( havepattern )
regfree ( & regexbuf ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2005-06-06 21:09:59 +00:00
# undef FORMAT
2005-06-06 20:27:51 +00:00
}
2005-06-07 16:07:06 +00:00
# endif /* ! LOW_MEMORY */
2005-06-06 20:27:51 +00:00
2003-08-07 03:48:00 +00:00
int ast_register_atexit ( void ( * func ) ( void ) )
{
struct ast_atexit * ae ;
2007-09-08 18:45:51 +00:00
if ( ! ( ae = ast_calloc ( 1 , sizeof ( * ae ) ) ) )
return - 1 ;
ae - > func = func ;
2006-02-14 22:28:01 +00:00
ast_unregister_atexit ( func ) ;
2007-09-08 18:45:51 +00:00
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & atexits ) ;
2007-09-08 18:45:51 +00:00
AST_RWLIST_INSERT_HEAD ( & atexits , ae , list ) ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_UNLOCK ( & atexits ) ;
2007-09-08 18:45:51 +00:00
return 0 ;
2003-08-07 03:48:00 +00:00
}
void ast_unregister_atexit ( void ( * func ) ( void ) )
{
2007-09-08 18:45:51 +00:00
struct ast_atexit * ae = NULL ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & atexits ) ;
AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & atexits , ae , list ) {
2003-08-07 03:48:00 +00:00
if ( ae - > func = = func ) {
2007-11-08 05:28:47 +00:00
AST_RWLIST_REMOVE_CURRENT ( list ) ;
2003-08-07 03:48:00 +00:00
break ;
}
}
2007-11-08 05:28:47 +00:00
AST_RWLIST_TRAVERSE_SAFE_END ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_UNLOCK ( & atexits ) ;
2007-09-08 18:45:51 +00:00
if ( ae )
free ( ae ) ;
2003-08-07 03:48:00 +00:00
}
2008-05-27 18:59:06 +00:00
/* Sending commands from consoles back to the daemon requires a terminating NULL */
static int fdsend ( int fd , const char * s )
2001-05-09 03:11:22 +00:00
{
return write ( fd , s , strlen ( s ) + 1 ) ;
}
2008-05-27 18:59:06 +00:00
/* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
static int fdprint ( int fd , const char * s )
{
return write ( fd , s , strlen ( s ) ) ;
}
2006-06-08 18:03:08 +00:00
/*! \brief NULL handler so we can collect the child exit status */
2008-08-10 19:35:50 +00:00
static void null_sig_handler ( int sig )
2004-08-22 18:33:19 +00:00
{
}
2005-09-14 22:40:54 +00:00
AST_MUTEX_DEFINE_STATIC ( safe_system_lock ) ;
2006-06-08 18:03:08 +00:00
/*! \brief Keep track of how many threads are currently trying to wait*() on
2006-05-25 18:31:19 +00:00
* a child process */
2005-09-14 22:40:54 +00:00
static unsigned int safe_system_level = 0 ;
static void * safe_system_prev_handler ;
2006-05-25 18:31:19 +00:00
void ast_replace_sigchld ( void )
2004-03-21 18:15:37 +00:00
{
2005-09-14 22:40:54 +00:00
unsigned int level ;
ast_mutex_lock ( & safe_system_lock ) ;
level = safe_system_level + + ;
/* only replace the handler if it has not already been done */
if ( level = = 0 )
safe_system_prev_handler = signal ( SIGCHLD , null_sig_handler ) ;
ast_mutex_unlock ( & safe_system_lock ) ;
2006-05-25 18:31:19 +00:00
}
void ast_unreplace_sigchld ( void )
{
unsigned int level ;
ast_mutex_lock ( & safe_system_lock ) ;
level = - - safe_system_level ;
/* only restore the handler if we are the last one */
if ( level = = 0 )
signal ( SIGCHLD , safe_system_prev_handler ) ;
ast_mutex_unlock ( & safe_system_lock ) ;
}
int ast_safe_system ( const char * s )
{
pid_t pid ;
int res ;
struct rusage rusage ;
int status ;
2006-09-16 23:53:58 +00:00
# if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
ast_replace_sigchld ( ) ;
2005-09-14 22:40:54 +00:00
2006-09-18 19:58:27 +00:00
# ifdef HAVE_WORKING_FORK
2004-03-21 18:15:37 +00:00
pid = fork ( ) ;
2006-09-18 19:58:27 +00:00
# else
pid = vfork ( ) ;
2006-09-16 23:53:58 +00:00
# endif
2005-09-14 22:40:54 +00:00
2004-03-21 18:15:37 +00:00
if ( pid = = 0 ) {
2009-01-29 23:15:40 +00:00
# ifdef HAVE_CAP
cap_t cap = cap_from_text ( " cap_net_admin-eip " ) ;
if ( cap_set_proc ( cap ) ) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log ( LOG_WARNING , " Unable to remove capabilities. \n " ) ;
}
cap_free ( cap ) ;
# endif
2006-10-18 21:05:52 +00:00
# ifdef HAVE_WORKING_FORK
2006-05-01 21:48:30 +00:00
if ( ast_opt_high_priority )
ast_set_priority ( 0 ) ;
2004-03-21 18:15:37 +00:00
/* Close file descriptors and launch system command */
2008-04-16 22:57:54 +00:00
ast_close_fds_above_n ( STDERR_FILENO ) ;
2006-10-18 21:05:52 +00:00
# endif
2006-06-09 20:26:25 +00:00
execl ( " /bin/sh " , " /bin/sh " , " -c " , s , ( char * ) NULL ) ;
2006-10-27 17:42:57 +00:00
_exit ( 1 ) ;
2004-03-21 18:15:37 +00:00
} else if ( pid > 0 ) {
2007-01-23 00:11:32 +00:00
for ( ; ; ) {
2004-03-21 18:15:37 +00:00
res = wait4 ( pid , & status , 0 , & rusage ) ;
if ( res > - 1 ) {
2005-09-14 22:40:54 +00:00
res = WIFEXITED ( status ) ? WEXITSTATUS ( status ) : - 1 ;
break ;
} else if ( errno ! = EINTR )
2004-06-21 19:12:20 +00:00
break ;
2004-03-21 18:15:37 +00:00
}
} else {
ast_log ( LOG_WARNING , " Fork failed: %s \n " , strerror ( errno ) ) ;
res = - 1 ;
}
2005-09-14 22:40:54 +00:00
2006-05-25 18:31:19 +00:00
ast_unreplace_sigchld ( ) ;
2009-01-29 23:15:40 +00:00
# else /* !defined(HAVE_WORKING_FORK) && !defined(HAVE_WORKING_VFORK) */
2006-08-21 20:12:18 +00:00
res = - 1 ;
# endif
2005-09-14 22:40:54 +00:00
2004-03-21 18:15:37 +00:00
return res ;
}
2008-05-29 21:30:37 +00:00
void ast_console_toggle_loglevel ( int fd , int level , int state )
{
int x ;
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
if ( fd = = consoles [ x ] . fd ) {
consoles [ x ] . levels [ level ] = state ;
return ;
}
}
}
2006-05-26 19:48:17 +00:00
/*!
2006-06-08 18:03:08 +00:00
* \ brief mute or unmute a console from logging
2006-05-26 19:48:17 +00:00
*/
2007-10-13 05:53:19 +00:00
void ast_console_toggle_mute ( int fd , int silent ) {
2006-05-26 19:48:17 +00:00
int x ;
2006-05-26 21:47:52 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
2006-05-26 19:48:17 +00:00
if ( fd = = consoles [ x ] . fd ) {
if ( consoles [ x ] . mute ) {
2006-05-26 21:47:52 +00:00
consoles [ x ] . mute = 0 ;
2007-10-13 05:53:19 +00:00
if ( ! silent )
ast_cli ( fd , " Console is not muted anymore. \n " ) ;
2006-05-26 19:48:17 +00:00
} else {
2006-05-26 21:47:52 +00:00
consoles [ x ] . mute = 1 ;
2007-10-13 05:53:19 +00:00
if ( ! silent )
ast_cli ( fd , " Console is muted. \n " ) ;
2006-05-26 19:48:17 +00:00
}
return ;
}
}
ast_cli ( fd , " Couldn't find remote console. \n " ) ;
}
/*!
2006-06-08 18:03:08 +00:00
* \ brief log the string to all attached console clients
2006-05-26 19:48:17 +00:00
*/
2008-05-29 21:30:37 +00:00
static void ast_network_puts_mutable ( const char * string , int level )
2006-05-26 19:48:17 +00:00
{
int x ;
2006-05-26 21:47:52 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
2006-05-26 19:48:17 +00:00
if ( consoles [ x ] . mute )
2006-05-26 21:47:52 +00:00
continue ;
2008-05-29 21:30:37 +00:00
if ( consoles [ x ] . fd > - 1 ) {
if ( ! consoles [ x ] . levels [ level ] )
fdprint ( consoles [ x ] . p [ 1 ] , string ) ;
}
2006-05-26 19:48:17 +00:00
}
}
/*!
2006-06-08 18:03:08 +00:00
* \ brief log the string to the console , and all attached
2006-05-26 19:48:17 +00:00
* console clients
*/
2008-05-29 21:30:37 +00:00
void ast_console_puts_mutable ( const char * string , int level )
2006-05-26 19:48:17 +00:00
{
fputs ( string , stdout ) ;
fflush ( stdout ) ;
2008-05-29 21:30:37 +00:00
ast_network_puts_mutable ( string , level ) ;
2006-05-26 19:48:17 +00:00
}
2005-10-24 20:12:06 +00:00
/*!
2006-06-08 18:03:08 +00:00
* \ brief write the string to all attached console clients
2004-01-12 05:05:35 +00:00
*/
static void ast_network_puts ( const char * string )
{
2004-06-29 04:42:19 +00:00
int x ;
2008-02-11 18:27:47 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
2004-06-29 04:42:19 +00:00
if ( consoles [ x ] . fd > - 1 )
fdprint ( consoles [ x ] . p [ 1 ] , string ) ;
}
2004-01-12 05:05:35 +00:00
}
2005-10-24 20:12:06 +00:00
/*!
2004-01-12 05:05:35 +00:00
* write the string to the console , and all attached
* console clients
*/
void ast_console_puts ( const char * string )
{
2004-06-29 04:42:19 +00:00
fputs ( string , stdout ) ;
fflush ( stdout ) ;
ast_network_puts ( string ) ;
2004-01-12 05:05:35 +00:00
}
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
static void network_verboser ( const char * s )
{
2008-05-29 21:30:37 +00:00
ast_network_puts_mutable ( s , __LOG_VERBOSE ) ;
2001-05-09 03:11:22 +00:00
}
static pthread_t lthread ;
2008-12-01 18:52:14 +00:00
/*!
* \ brief read ( ) function supporting the reception of user credentials .
*
* \ param fd Socket file descriptor .
* \ param buffer Receive buffer .
* \ param size ' buffer ' size .
* \ param con Console structure to set received credentials
* \ retval - 1 on error
* \ retval the number of bytes received on success .
*/
static int read_credentials ( int fd , char * buffer , size_t size , struct console * con )
{
# if defined(SO_PEERCRED)
struct ucred cred ;
socklen_t len = sizeof ( cred ) ;
# endif
2009-01-14 19:36:57 +00:00
# if defined(HAVE_GETPEEREID)
uid_t uid ;
gid_t gid ;
# else
int uid , gid ;
# endif
int result ;
2008-12-01 18:52:14 +00:00
result = read ( fd , buffer , size ) ;
if ( result < 0 ) {
return result ;
}
# if defined(SO_PEERCRED)
if ( getsockopt ( fd , SOL_SOCKET , SO_PEERCRED , & cred , & len ) ) {
return result ;
}
uid = cred . uid ;
gid = cred . gid ;
# elif defined(HAVE_GETPEEREID)
if ( getpeereid ( fd , & uid , & gid ) ) {
return result ;
}
# else
return result ;
# endif
con - > uid = uid ;
con - > gid = gid ;
return result ;
}
2001-05-09 03:11:22 +00:00
static void * netconsole ( void * vconsole )
{
struct console * con = vconsole ;
2006-03-31 00:33:28 +00:00
char hostname [ MAXHOSTNAMELEN ] = " " ;
2001-05-09 03:11:22 +00:00
char tmp [ 512 ] ;
int res ;
2004-04-25 20:42:45 +00:00
struct pollfd fds [ 2 ] ;
2001-05-09 03:11:22 +00:00
2005-05-08 16:44:25 +00:00
if ( gethostname ( hostname , sizeof ( hostname ) - 1 ) )
2005-06-05 16:32:16 +00:00
ast_copy_string ( hostname , " <Unknown> " , sizeof ( hostname ) ) ;
Now that the version.h file was getting properly regenerated every time the svn
revision changed, every module that used the version was getting rebuilt after
every svn update. This severly annoyed me pretty quickly, so I have improved
the situation.
Now, instead of generating version.h, main/version.c is generated. version.c
includes the version information, as well as a couple of API calls for modules
to retrieve the version. So now, only version.c will get rebuilt, and the main
asterisk binary relinked, which is must faster than rebuilding http.c, manager.c,
asterisk.c, relinking the asterisk binary, chan_sip.c, func_version.c, res_agi ...
The only minor change in behavior here is that the version information reported by
chan_sip, for example, is the version of the Asterisk core, and not necessarily the
Asterisk version that the chan_sip module came from.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@96717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-01-05 22:09:06 +00:00
snprintf ( tmp , sizeof ( tmp ) , " %s/%ld/%s \n " , hostname , ( long ) ast_mainpid , ast_get_version ( ) ) ;
2001-05-09 03:11:22 +00:00
fdprint ( con - > fd , tmp ) ;
2007-01-23 00:11:32 +00:00
for ( ; ; ) {
2004-04-25 20:42:45 +00:00
fds [ 0 ] . fd = con - > fd ;
fds [ 0 ] . events = POLLIN ;
2005-08-31 22:12:23 +00:00
fds [ 0 ] . revents = 0 ;
2004-04-25 20:42:45 +00:00
fds [ 1 ] . fd = con - > p [ 0 ] ;
fds [ 1 ] . events = POLLIN ;
2005-08-31 22:12:23 +00:00
fds [ 1 ] . revents = 0 ;
2004-04-25 20:42:45 +00:00
res = poll ( fds , 2 , - 1 ) ;
2001-05-09 03:11:22 +00:00
if ( res < 0 ) {
2004-05-07 14:08:50 +00:00
if ( errno ! = EINTR )
ast_log ( LOG_WARNING , " poll returned < 0: %s \n " , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
continue ;
}
2004-04-25 20:42:45 +00:00
if ( fds [ 0 ] . revents ) {
2008-12-01 18:52:14 +00:00
res = read_credentials ( con - > fd , tmp , sizeof ( tmp ) , con ) ;
2001-10-11 18:51:39 +00:00
if ( res < 1 ) {
2001-05-09 03:11:22 +00:00
break ;
2001-10-11 18:51:39 +00:00
}
2001-05-09 03:11:22 +00:00
tmp [ res ] = 0 ;
2008-07-08 20:17:08 +00:00
if ( strncmp ( tmp , " cli quit after " , 15 ) = = 0 ) {
2008-12-01 18:52:14 +00:00
ast_cli_command_multiple_full ( con - > uid , con - > gid , con - > fd , res - 15 , tmp + 15 ) ;
2008-07-08 20:17:08 +00:00
break ;
}
2008-12-01 18:52:14 +00:00
ast_cli_command_multiple_full ( con - > uid , con - > gid , con - > fd , res , tmp ) ;
2001-05-09 03:11:22 +00:00
}
2004-04-25 20:42:45 +00:00
if ( fds [ 1 ] . revents ) {
2008-12-01 18:52:14 +00:00
res = read_credentials ( con - > p [ 0 ] , tmp , sizeof ( tmp ) , con ) ;
2001-05-09 03:11:22 +00:00
if ( res < 1 ) {
ast_log ( LOG_ERROR , " read returned %d \n " , res ) ;
break ;
}
res = write ( con - > fd , tmp , res ) ;
if ( res < 1 )
break ;
}
}
2009-01-13 23:00:27 +00:00
if ( ! ast_opt_hide_connect ) {
ast_verb ( 3 , " Remote UNIX connection disconnected \n " ) ;
}
2001-05-09 03:11:22 +00:00
close ( con - > fd ) ;
close ( con - > p [ 0 ] ) ;
close ( con - > p [ 1 ] ) ;
con - > fd = - 1 ;
return NULL ;
}
static void * listener ( void * unused )
{
2004-12-14 23:36:30 +00:00
struct sockaddr_un sunaddr ;
2001-05-09 03:11:22 +00:00
int s ;
2005-05-15 03:21:51 +00:00
socklen_t len ;
2001-05-09 03:11:22 +00:00
int x ;
2001-10-11 18:51:39 +00:00
int flags ;
2004-04-25 20:42:45 +00:00
struct pollfd fds [ 1 ] ;
2006-03-31 00:33:28 +00:00
for ( ; ; ) {
2002-09-12 03:22:07 +00:00
if ( ast_socket < 0 )
return NULL ;
2004-04-25 20:42:45 +00:00
fds [ 0 ] . fd = ast_socket ;
2006-03-31 00:33:28 +00:00
fds [ 0 ] . events = POLLIN ;
2004-04-25 20:42:45 +00:00
s = poll ( fds , 1 , - 1 ) ;
2006-07-03 05:14:06 +00:00
pthread_testcancel ( ) ;
2003-09-29 20:20:04 +00:00
if ( s < 0 ) {
2004-03-04 21:32:32 +00:00
if ( errno ! = EINTR )
2004-04-25 20:42:45 +00:00
ast_log ( LOG_WARNING , " poll returned error: %s \n " , strerror ( errno ) ) ;
2003-09-29 20:20:04 +00:00
continue ;
}
2004-12-14 23:36:30 +00:00
len = sizeof ( sunaddr ) ;
s = accept ( ast_socket , ( struct sockaddr * ) & sunaddr , & len ) ;
2001-05-09 03:11:22 +00:00
if ( s < 0 ) {
2004-03-02 16:58:17 +00:00
if ( errno ! = EINTR )
2004-03-03 00:05:00 +00:00
ast_log ( LOG_WARNING , " Accept returned %d: %s \n " , s , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
} else {
2008-12-01 18:52:14 +00:00
# if !defined(SO_PASSCRED)
{
# else
int sckopt = 1 ;
/* turn on socket credentials passing. */
if ( setsockopt ( s , SOL_SOCKET , SO_PASSCRED , & sckopt , sizeof ( sckopt ) ) < 0 ) {
ast_log ( LOG_WARNING , " Unable to turn on socket credentials passing \n " ) ;
} else {
# endif
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
if ( consoles [ x ] . fd > = 0 ) {
continue ;
}
2001-10-11 18:51:39 +00:00
if ( socketpair ( AF_LOCAL , SOCK_STREAM , 0 , consoles [ x ] . p ) ) {
2001-05-09 03:11:22 +00:00
ast_log ( LOG_ERROR , " Unable to create pipe: %s \n " , strerror ( errno ) ) ;
consoles [ x ] . fd = - 1 ;
fdprint ( s , " Server failed to create pipe \n " ) ;
close ( s ) ;
break ;
}
2001-10-11 18:51:39 +00:00
flags = fcntl ( consoles [ x ] . p [ 1 ] , F_GETFL ) ;
fcntl ( consoles [ x ] . p [ 1 ] , F_SETFL , flags | O_NONBLOCK ) ;
2001-05-09 03:11:22 +00:00
consoles [ x ] . fd = s ;
2007-10-13 05:53:19 +00:00
consoles [ x ] . mute = 1 ; /* Default is muted, we will un-mute if necessary */
2008-12-01 18:52:14 +00:00
/* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
to know if the user didn ' t send the credentials . */
consoles [ x ] . uid = - 2 ;
consoles [ x ] . gid = - 2 ;
2007-05-24 18:30:19 +00:00
if ( ast_pthread_create_detached_background ( & consoles [ x ] . t , NULL , netconsole , & consoles [ x ] ) ) {
2004-05-07 14:08:50 +00:00
ast_log ( LOG_ERROR , " Unable to spawn thread to handle connection: %s \n " , strerror ( errno ) ) ;
2006-04-11 21:58:44 +00:00
close ( consoles [ x ] . p [ 0 ] ) ;
close ( consoles [ x ] . p [ 1 ] ) ;
2001-05-09 03:11:22 +00:00
consoles [ x ] . fd = - 1 ;
fdprint ( s , " Server failed to spawn thread \n " ) ;
close ( s ) ;
}
break ;
}
2008-12-01 18:52:14 +00:00
if ( x > = AST_MAX_CONNECTS ) {
fdprint ( s , " No more connections allowed \n " ) ;
ast_log ( LOG_WARNING , " No more connections allowed \n " ) ;
close ( s ) ;
2009-01-13 23:00:27 +00:00
} else if ( ( consoles [ x ] . fd > - 1 ) & & ( ! ast_opt_hide_connect ) ) {
2008-12-01 18:52:14 +00:00
ast_verb ( 3 , " Remote UNIX connection \n " ) ;
2009-01-13 23:00:27 +00:00
}
2001-05-09 03:11:22 +00:00
}
}
}
return NULL ;
}
static int ast_makesocket ( void )
{
2004-12-14 23:36:30 +00:00
struct sockaddr_un sunaddr ;
2001-05-09 03:11:22 +00:00
int res ;
int x ;
2005-07-25 23:09:13 +00:00
uid_t uid = - 1 ;
gid_t gid = - 1 ;
2005-02-11 21:16:34 +00:00
2005-07-25 23:09:13 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + )
2001-05-09 03:11:22 +00:00
consoles [ x ] . fd = - 1 ;
2005-07-25 23:09:13 +00:00
unlink ( ast_config_AST_SOCKET ) ;
2001-05-09 03:11:22 +00:00
ast_socket = socket ( PF_LOCAL , SOCK_STREAM , 0 ) ;
if ( ast_socket < 0 ) {
ast_log ( LOG_WARNING , " Unable to create control socket: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
2004-12-14 23:36:30 +00:00
memset ( & sunaddr , 0 , sizeof ( sunaddr ) ) ;
sunaddr . sun_family = AF_LOCAL ;
2005-07-25 23:09:13 +00:00
ast_copy_string ( sunaddr . sun_path , ast_config_AST_SOCKET , sizeof ( sunaddr . sun_path ) ) ;
2004-12-14 23:36:30 +00:00
res = bind ( ast_socket , ( struct sockaddr * ) & sunaddr , sizeof ( sunaddr ) ) ;
2001-05-09 03:11:22 +00:00
if ( res ) {
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to bind socket to %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
ast_socket = - 1 ;
return - 1 ;
}
res = listen ( ast_socket , 2 ) ;
if ( res < 0 ) {
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to listen on socket %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
ast_socket = - 1 ;
return - 1 ;
}
2008-05-02 02:33:04 +00:00
if ( ast_register_verbose ( network_verboser ) ) {
ast_log ( LOG_WARNING , " Unable to register network verboser? \n " ) ;
}
2006-10-04 19:51:38 +00:00
ast_pthread_create_background ( & lthread , NULL , listener , NULL ) ;
2005-02-11 21:16:34 +00:00
2005-07-25 23:09:13 +00:00
if ( ! ast_strlen_zero ( ast_config_AST_CTL_OWNER ) ) {
2005-02-11 21:16:34 +00:00
struct passwd * pw ;
2006-10-29 20:47:01 +00:00
if ( ( pw = getpwnam ( ast_config_AST_CTL_OWNER ) ) = = NULL )
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to find uid of user %s \n " , ast_config_AST_CTL_OWNER ) ;
2006-10-29 20:47:01 +00:00
else
2005-07-25 23:09:13 +00:00
uid = pw - > pw_uid ;
2005-02-11 21:16:34 +00:00
}
2005-07-25 23:09:13 +00:00
if ( ! ast_strlen_zero ( ast_config_AST_CTL_GROUP ) ) {
2005-02-11 21:16:34 +00:00
struct group * grp ;
2006-10-29 20:47:01 +00:00
if ( ( grp = getgrnam ( ast_config_AST_CTL_GROUP ) ) = = NULL )
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to find gid of group %s \n " , ast_config_AST_CTL_GROUP ) ;
2006-10-29 20:47:01 +00:00
else
2005-07-25 23:09:13 +00:00
gid = grp - > gr_gid ;
2005-02-11 21:16:34 +00:00
}
2005-07-25 23:09:13 +00:00
if ( chown ( ast_config_AST_SOCKET , uid , gid ) < 0 )
ast_log ( LOG_WARNING , " Unable to change ownership of %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
if ( ! ast_strlen_zero ( ast_config_AST_CTL_PERMISSIONS ) ) {
2005-12-26 18:35:28 +00:00
int p1 ;
2005-02-11 21:16:34 +00:00
mode_t p ;
2005-12-26 18:35:28 +00:00
sscanf ( ast_config_AST_CTL_PERMISSIONS , " %o " , & p1 ) ;
p = p1 ;
2005-07-25 23:09:13 +00:00
if ( ( chmod ( ast_config_AST_SOCKET , p ) ) < 0 )
ast_log ( LOG_WARNING , " Unable to change file permissions of %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
2005-02-11 21:16:34 +00:00
}
2001-05-09 03:11:22 +00:00
return 0 ;
}
static int ast_tryconnect ( void )
{
2004-12-14 23:36:30 +00:00
struct sockaddr_un sunaddr ;
2001-05-09 03:11:22 +00:00
int res ;
ast_consock = socket ( PF_LOCAL , SOCK_STREAM , 0 ) ;
if ( ast_consock < 0 ) {
ast_log ( LOG_WARNING , " Unable to create socket: %s \n " , strerror ( errno ) ) ;
return 0 ;
}
2004-12-14 23:36:30 +00:00
memset ( & sunaddr , 0 , sizeof ( sunaddr ) ) ;
sunaddr . sun_family = AF_LOCAL ;
2007-12-18 09:46:18 +00:00
ast_copy_string ( sunaddr . sun_path , ast_config_AST_SOCKET , sizeof ( sunaddr . sun_path ) ) ;
2004-12-14 23:36:30 +00:00
res = connect ( ast_consock , ( struct sockaddr * ) & sunaddr , sizeof ( sunaddr ) ) ;
2001-05-09 03:11:22 +00:00
if ( res ) {
close ( ast_consock ) ;
ast_consock = - 1 ;
return 0 ;
} else
return 1 ;
}
2006-06-08 18:03:08 +00:00
/*! \brief Urgent handler
2005-10-24 20:12:06 +00:00
Called by soft_hangup to interrupt the poll , read , or other
system call . We don ' t actually need to do anything though .
Remember : Cannot EVER ast_log from within a signal handler
*/
1999-11-15 04:57:28 +00:00
static void urg_handler ( int num )
{
2000-01-02 20:59:00 +00:00
signal ( num , urg_handler ) ;
1999-11-15 04:57:28 +00:00
return ;
}
2001-05-09 03:11:22 +00:00
static void hup_handler ( int num )
{
2007-02-23 23:25:22 +00:00
int a = 0 ;
2001-05-09 03:11:22 +00:00
if ( option_verbose > 1 )
2003-12-01 02:47:19 +00:00
printf ( " Received HUP signal -- Reloading configs \n " ) ;
2004-02-23 03:43:21 +00:00
if ( restartnow )
execvp ( _argv [ 0 ] , _argv ) ;
2007-02-23 23:25:22 +00:00
sig_flags . need_reload = 1 ;
2008-11-02 18:52:13 +00:00
if ( sig_alert_pipe [ 1 ] ! = - 1 ) {
if ( write ( sig_alert_pipe [ 1 ] , & a , sizeof ( a ) ) < 0 ) {
fprintf ( stderr , " hup_handler: write() failed: %s \n " , strerror ( errno ) ) ;
}
}
2005-07-15 22:12:55 +00:00
signal ( num , hup_handler ) ;
2001-05-09 03:11:22 +00:00
}
2003-09-16 19:35:57 +00:00
static void child_handler ( int sig )
2001-05-09 03:11:22 +00:00
{
2003-12-01 02:47:19 +00:00
/* Must not ever ast_log or ast_verbose within signal handler */
2003-09-16 19:35:57 +00:00
int n , status ;
/*
* Reap all dead children - - not just one
*/
for ( n = 0 ; wait4 ( - 1 , & status , WNOHANG , NULL ) > 0 ; n + + )
;
if ( n = = 0 & & option_debug )
2003-12-01 02:47:19 +00:00
printf ( " Huh? Child handler, but nobody there? \n " ) ;
2005-07-15 22:12:55 +00:00
signal ( sig , child_handler ) ;
2001-05-09 03:11:22 +00:00
}
2003-09-16 19:35:57 +00:00
2006-11-22 17:41:07 +00:00
/*! \brief Set maximum open files */
static void set_ulimit ( int value )
{
struct rlimit l = { 0 , 0 } ;
if ( value < = 0 ) {
ast_log ( LOG_WARNING , " Unable to change max files open to invalid value %i \n " , value ) ;
return ;
}
l . rlim_cur = value ;
l . rlim_max = value ;
if ( setrlimit ( RLIMIT_NOFILE , & l ) ) {
ast_log ( LOG_WARNING , " Unable to disable core size resource limit: %s \n " , strerror ( errno ) ) ;
return ;
}
ast_log ( LOG_NOTICE , " Setting max files open to %d \n " , value ) ;
return ;
}
2006-06-08 18:03:08 +00:00
/*! \brief Set an X-term or screen title */
2000-10-25 23:22:50 +00:00
static void set_title ( char * text )
{
if ( getenv ( " TERM " ) & & strstr ( getenv ( " TERM " ) , " xterm " ) )
fprintf ( stdout , " \033 ]2;%s \007 " , text ) ;
}
static void set_icon ( char * text )
{
if ( getenv ( " TERM " ) & & strstr ( getenv ( " TERM " ) , " xterm " ) )
fprintf ( stdout , " \033 ]1;%s \007 " , text ) ;
}
2006-06-08 18:03:08 +00:00
/*! \brief We set ourselves to a high priority, that we might pre-empt everything
2005-10-24 20:12:06 +00:00
else . If your PBX has heavy activity on it , this is a good thing . */
2005-08-23 01:30:22 +00:00
int ast_set_priority ( int pri )
1999-12-19 22:38:55 +00:00
{
struct sched_param sched ;
2001-03-22 04:14:04 +00:00
memset ( & sched , 0 , sizeof ( sched ) ) ;
2003-04-23 20:22:14 +00:00
# ifdef __linux__
1999-12-19 22:38:55 +00:00
if ( pri ) {
2001-03-22 04:14:04 +00:00
sched . sched_priority = 10 ;
if ( sched_setscheduler ( 0 , SCHED_RR , & sched ) ) {
1999-12-19 22:38:55 +00:00
ast_log ( LOG_WARNING , " Unable to set high priority \n " ) ;
return - 1 ;
2001-03-22 04:14:04 +00:00
} else
if ( option_verbose )
ast_verbose ( " Set to realtime thread \n " ) ;
1999-12-19 22:38:55 +00:00
} else {
sched . sched_priority = 0 ;
2007-04-09 03:04:07 +00:00
/* According to the manpage, these parameters can never fail. */
sched_setscheduler ( 0 , SCHED_OTHER , & sched ) ;
1999-12-19 22:38:55 +00:00
}
2003-04-23 20:22:14 +00:00
# else
if ( pri ) {
if ( setpriority ( PRIO_PROCESS , 0 , - 10 ) = = - 1 ) {
ast_log ( LOG_WARNING , " Unable to set high priority \n " ) ;
return - 1 ;
} else
if ( option_verbose )
ast_verbose ( " Set to high priority \n " ) ;
} else {
2007-04-09 03:04:07 +00:00
/* According to the manpage, these parameters can never fail. */
setpriority ( PRIO_PROCESS , 0 , 0 ) ;
2003-04-23 20:22:14 +00:00
}
# endif
1999-12-19 22:38:55 +00:00
return 0 ;
}
2003-08-07 03:48:00 +00:00
static void ast_run_atexits ( void )
{
struct ast_atexit * ae ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_RDLOCK ( & atexits ) ;
AST_RWLIST_TRAVERSE ( & atexits , ae , list ) {
2003-08-07 03:48:00 +00:00
if ( ae - > func )
ae - > func ( ) ;
}
2007-06-18 16:37:14 +00:00
AST_RWLIST_UNLOCK ( & atexits ) ;
2003-08-07 03:48:00 +00:00
}
2008-08-10 19:35:50 +00:00
static void quit_handler ( int num , int niceness , int safeshutdown , int restart )
1999-11-15 04:57:28 +00:00
{
1999-12-19 22:38:55 +00:00
char filename [ 80 ] = " " ;
2002-05-14 14:43:52 +00:00
time_t s , e ;
int x ;
2005-06-03 01:42:31 +00:00
/* Try to get as many CDRs as possible submitted to the backend engines (if in batch mode) */
ast_cdr_engine_term ( ) ;
2002-05-14 14:43:52 +00:00
if ( safeshutdown ) {
shuttingdown = 1 ;
2008-08-10 19:35:50 +00:00
if ( ! niceness ) {
2002-05-14 14:43:52 +00:00
/* Begin shutdown routine, hanging up active channels */
ast_begin_shutdown ( 1 ) ;
2005-12-04 20:40:46 +00:00
if ( option_verbose & & ast_opt_console )
2002-05-14 14:43:52 +00:00
ast_verbose ( " Beginning asterisk %s.... \n " , restart ? " restart " : " shutdown " ) ;
time ( & s ) ;
2006-03-31 00:33:28 +00:00
for ( ; ; ) {
2002-05-14 14:43:52 +00:00
time ( & e ) ;
/* Wait up to 15 seconds for all channels to go away */
if ( ( e - s ) > 15 )
break ;
if ( ! ast_active_channels ( ) )
break ;
if ( ! shuttingdown )
break ;
/* Sleep 1/10 of a second */
usleep ( 100000 ) ;
}
} else {
2008-08-10 19:35:50 +00:00
if ( niceness < 2 )
2002-05-14 14:43:52 +00:00
ast_begin_shutdown ( 0 ) ;
2005-12-04 20:40:46 +00:00
if ( option_verbose & & ast_opt_console )
2002-05-14 14:43:52 +00:00
ast_verbose ( " Waiting for inactivity to perform %s... \n " , restart ? " restart " : " halt " ) ;
2006-03-31 00:33:28 +00:00
for ( ; ; ) {
2002-05-14 14:43:52 +00:00
if ( ! ast_active_channels ( ) )
break ;
if ( ! shuttingdown )
break ;
sleep ( 1 ) ;
}
}
if ( ! shuttingdown ) {
2005-12-04 20:40:46 +00:00
if ( option_verbose & & ast_opt_console )
2002-05-14 14:43:52 +00:00
ast_verbose ( " Asterisk %s cancelled. \n " , restart ? " restart " : " shutdown " ) ;
return ;
}
2007-06-05 15:54:36 +00:00
2008-08-10 19:35:50 +00:00
if ( niceness )
2007-06-05 15:54:36 +00:00
ast_module_shutdown ( ) ;
2002-05-14 14:43:52 +00:00
}
2008-11-05 22:19:18 +00:00
if ( ast_opt_console | | ( ast_opt_remote & & ! ast_opt_exec ) ) {
2001-05-09 03:11:22 +00:00
if ( getenv ( " HOME " ) )
snprintf ( filename , sizeof ( filename ) , " %s/.asterisk_history " , getenv ( " HOME " ) ) ;
2004-05-04 14:54:42 +00:00
if ( ! ast_strlen_zero ( filename ) )
2003-02-06 06:15:25 +00:00
ast_el_write_history ( filename ) ;
if ( el ! = NULL )
el_end ( el ) ;
if ( el_hist ! = NULL )
history_end ( el_hist ) ;
2001-05-09 03:11:22 +00:00
}
2003-08-07 03:48:00 +00:00
if ( option_verbose )
ast_verbose ( " Executing last minute cleanups \n " ) ;
ast_run_atexits ( ) ;
1999-11-15 04:57:28 +00:00
/* Called on exit */
2005-12-04 20:40:46 +00:00
if ( option_verbose & & ast_opt_console )
2002-05-14 14:43:52 +00:00
ast_verbose ( " Asterisk %s ending (%d). \n " , ast_active_channels ( ) ? " uncleanly " : " cleanly " , num ) ;
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Asterisk ending (%d). \n " , num ) ;
2003-02-20 06:00:14 +00:00
manager_event ( EVENT_FLAG_SYSTEM , " Shutdown " , " Shutdown: %s \r \n Restart: %s \r \n " , ast_active_channels ( ) ? " Uncleanly " : " Cleanly " , restart ? " True " : " False " ) ;
2002-09-12 03:22:07 +00:00
if ( ast_socket > - 1 ) {
2006-07-03 05:14:06 +00:00
pthread_cancel ( lthread ) ;
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
2002-09-12 03:22:07 +00:00
ast_socket = - 1 ;
2006-03-25 23:22:44 +00:00
unlink ( ast_config_AST_SOCKET ) ;
2002-09-12 03:22:07 +00:00
}
2001-05-09 03:11:22 +00:00
if ( ast_consock > - 1 )
close ( ast_consock ) ;
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_remote )
unlink ( ast_config_AST_PID ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2002-05-14 14:43:52 +00:00
if ( restart ) {
2005-12-04 20:40:46 +00:00
if ( option_verbose | | ast_opt_console )
2002-05-14 14:43:52 +00:00
ast_verbose ( " Preparing for Asterisk restart... \n " ) ;
/* Mark all FD's for closing on exec */
2006-03-31 00:33:28 +00:00
for ( x = 3 ; x < 32768 ; x + + ) {
2002-05-14 14:43:52 +00:00
fcntl ( x , F_SETFD , FD_CLOEXEC ) ;
}
2005-12-04 20:40:46 +00:00
if ( option_verbose | | ast_opt_console )
2007-02-16 17:26:20 +00:00
ast_verbose ( " Asterisk is now restarting... \n " ) ;
2004-02-23 03:43:21 +00:00
restartnow = 1 ;
2004-06-17 01:13:10 +00:00
/* close logger */
close_logger ( ) ;
2004-02-23 03:43:21 +00:00
/* If there is a consolethread running send it a SIGHUP
so it can execvp , otherwise we can do it ourselves */
2005-09-25 16:52:04 +00:00
if ( ( consolethread ! = AST_PTHREADT_NULL ) & & ( consolethread ! = pthread_self ( ) ) ) {
2004-02-23 03:43:21 +00:00
pthread_kill ( consolethread , SIGHUP ) ;
2004-03-02 23:50:03 +00:00
/* Give the signal handler some time to complete */
sleep ( 2 ) ;
} else
2004-02-23 03:43:21 +00:00
execvp ( _argv [ 0 ] , _argv ) ;
2004-06-17 01:13:10 +00:00
} else {
/* close logger */
close_logger ( ) ;
2003-08-07 03:48:00 +00:00
}
exit ( 0 ) ;
2002-05-14 14:43:52 +00:00
}
static void __quit_handler ( int num )
{
2007-02-23 23:25:22 +00:00
int a = 0 ;
sig_flags . need_quit = 1 ;
2008-11-02 18:52:13 +00:00
if ( sig_alert_pipe [ 1 ] ! = - 1 ) {
if ( write ( sig_alert_pipe [ 1 ] , & a , sizeof ( a ) ) < 0 ) {
fprintf ( stderr , " hup_handler: write() failed: %s \n " , strerror ( errno ) ) ;
}
}
2007-02-23 23:25:22 +00:00
/* There is no need to restore the signal handler here, since the app
* is going to exit */
1999-11-15 04:57:28 +00:00
}
2008-12-11 23:38:56 +00:00
static void __remote_quit_handler ( int num )
{
sig_flags . need_quit = 1 ;
}
2003-06-27 23:02:52 +00:00
static const char * fix_header ( char * outbuf , int maxout , const char * s , char * cmp )
2002-05-14 14:43:52 +00:00
{
2003-06-27 23:02:52 +00:00
const char * c ;
2008-05-05 23:00:31 +00:00
/* Check for verboser preamble */
if ( * s = = 127 ) {
s + + ;
}
2003-06-27 23:02:52 +00:00
if ( ! strncmp ( s , cmp , strlen ( cmp ) ) ) {
c = s + strlen ( cmp ) ;
2002-05-14 14:43:52 +00:00
term_color ( outbuf , cmp , COLOR_GRAY , 0 , maxout ) ;
2003-06-27 23:02:52 +00:00
return c ;
2002-05-14 14:43:52 +00:00
}
2003-06-27 23:02:52 +00:00
return NULL ;
2002-05-14 14:43:52 +00:00
}
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
static void console_verboser ( const char * s )
1999-12-19 22:38:55 +00:00
{
2002-05-14 14:43:52 +00:00
char tmp [ 80 ] ;
2006-03-31 00:33:28 +00:00
const char * c = NULL ;
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
if ( ( c = fix_header ( tmp , sizeof ( tmp ) , s , VERBOSE_PREFIX_4 ) ) | |
( c = fix_header ( tmp , sizeof ( tmp ) , s , VERBOSE_PREFIX_3 ) ) | |
( c = fix_header ( tmp , sizeof ( tmp ) , s , VERBOSE_PREFIX_2 ) ) | |
( c = fix_header ( tmp , sizeof ( tmp ) , s , VERBOSE_PREFIX_1 ) ) ) {
fputs ( tmp , stdout ) ;
fputs ( c , stdout ) ;
2008-05-21 18:12:19 +00:00
} else {
if ( * s = = 127 ) {
s + + ;
}
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
fputs ( s , stdout ) ;
2008-05-21 18:12:19 +00:00
}
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
2000-01-02 20:59:00 +00:00
fflush ( stdout ) ;
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
/* Wake up a poll()ing console */
if ( ast_opt_console & & consolethread ! = AST_PTHREADT_NULL )
pthread_kill ( consolethread , SIGURG ) ;
1999-12-19 22:38:55 +00:00
}
2004-08-01 18:12:52 +00:00
static int ast_all_zeros ( char * s )
{
2006-03-31 00:33:28 +00:00
while ( * s ) {
2004-08-01 18:12:52 +00:00
if ( * s > 32 )
return 0 ;
s + + ;
}
return 1 ;
}
1999-12-19 22:38:55 +00:00
static void consolehandler ( char * s )
{
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_end ( ) ) ;
2002-05-14 14:43:52 +00:00
fflush ( stdout ) ;
2006-07-12 14:04:16 +00:00
1999-12-19 22:38:55 +00:00
/* Called when readline data is available */
2006-07-12 14:04:16 +00:00
if ( ! ast_all_zeros ( s ) )
2003-02-06 06:15:25 +00:00
ast_el_add_history ( s ) ;
2006-07-12 14:04:16 +00:00
/* The real handler for bang */
if ( s [ 0 ] = = ' ! ' ) {
if ( s [ 1 ] )
ast_safe_system ( s + 1 ) ;
else
ast_safe_system ( getenv ( " SHELL " ) ? getenv ( " SHELL " ) : " /bin/sh " ) ;
} else
1999-12-19 22:38:55 +00:00
ast_cli_command ( STDOUT_FILENO , s ) ;
}
2003-02-06 06:15:25 +00:00
static int remoteconsolehandler ( char * s )
2001-05-09 03:11:22 +00:00
{
2003-02-06 06:15:25 +00:00
int ret = 0 ;
2006-07-12 14:04:16 +00:00
2001-05-09 03:11:22 +00:00
/* Called when readline data is available */
2006-07-12 14:04:16 +00:00
if ( ! ast_all_zeros ( s ) )
2003-02-06 06:15:25 +00:00
ast_el_add_history ( s ) ;
2006-07-12 14:04:16 +00:00
/* The real handler for bang */
if ( s [ 0 ] = = ' ! ' ) {
if ( s [ 1 ] )
ast_safe_system ( s + 1 ) ;
else
ast_safe_system ( getenv ( " SHELL " ) ? getenv ( " SHELL " ) : " /bin/sh " ) ;
ret = 1 ;
}
if ( ( strncasecmp ( s , " quit " , 4 ) = = 0 | | strncasecmp ( s , " exit " , 4 ) = = 0 ) & &
( s [ 4 ] = = ' \0 ' | | isspace ( s [ 4 ] ) ) ) {
quit_handler ( 0 , 0 , 0 , 0 ) ;
ret = 1 ;
}
2003-02-06 06:15:25 +00:00
return ret ;
2001-05-09 03:11:22 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_version ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2006-04-29 00:15:28 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show version " ;
e - > usage =
" Usage: core show version \n "
" Shows Asterisk version information. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
if ( a - > argc ! = 3 )
return CLI_SHOWUSAGE ;
ast_cli ( a - > fd , " Asterisk %s built by %s @ %s on a %s running %s on %s \n " ,
Now that the version.h file was getting properly regenerated every time the svn
revision changed, every module that used the version was getting rebuilt after
every svn update. This severly annoyed me pretty quickly, so I have improved
the situation.
Now, instead of generating version.h, main/version.c is generated. version.c
includes the version information, as well as a couple of API calls for modules
to retrieve the version. So now, only version.c will get rebuilt, and the main
asterisk binary relinked, which is must faster than rebuilding http.c, manager.c,
asterisk.c, relinking the asterisk binary, chan_sip.c, func_version.c, res_agi ...
The only minor change in behavior here is that the version information reported by
chan_sip, for example, is the version of the Asterisk core, and not necessarily the
Asterisk version that the chan_sip module came from.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@96717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-01-05 22:09:06 +00:00
ast_get_version ( ) , ast_build_user , ast_build_hostname ,
2006-04-29 00:15:28 +00:00
ast_build_machine , ast_build_os , ast_build_date ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2006-04-29 00:15:28 +00:00
}
2003-03-16 22:37:31 +00:00
#if 0
1999-12-19 22:38:55 +00:00
static int handle_quit ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 1 )
return RESULT_SHOWUSAGE ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 0 , 1 , 0 ) ;
return RESULT_SUCCESS ;
}
2003-03-16 22:37:31 +00:00
# endif
2002-05-14 14:43:52 +00:00
2007-10-11 19:03:06 +00:00
static char * handle_stop_now ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core stop now " ;
2007-10-11 19:03:06 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core stop now \n "
2007-10-11 19:03:06 +00:00
" Shuts down a running Asterisk immediately, hanging up all active calls . \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 0 /* Not nice */ , 1 /* safely */ , 0 /* not restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_stop_gracefully ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core stop gracefully " ;
2007-10-11 19:03:06 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core stop gracefully \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to not accept new calls, and exit when all \n "
" active calls have terminated normally. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 1 /* nicely */ , 1 /* safely */ , 0 /* no restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_stop_when_convenient ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2003-04-23 16:24:09 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core stop when convenient " ;
2007-10-11 19:03:06 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core stop when convenient \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to perform a shutdown when all active calls have ended. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
ast_cli ( a - > fd , " Waiting for inactivity to perform halt \n " ) ;
2003-04-23 16:24:09 +00:00
quit_handler ( 0 , 2 /* really nicely */ , 1 /* safely */ , 0 /* don't restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2003-04-23 16:24:09 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_restart_now ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core restart now " ;
2007-10-11 19:03:06 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core restart now \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to hangup all calls and exec() itself performing a cold \n "
" restart. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 0 /* not nicely */ , 1 /* safely */ , 1 /* restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_restart_gracefully ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core restart gracefully " ;
2007-10-11 19:03:06 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core restart gracefully \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to stop accepting new calls and exec() itself performing a cold \n "
" restart when all active calls have ended. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 1 /* nicely */ , 1 /* safely */ , 1 /* restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_restart_when_convenient ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core restart when convenient " ;
2007-10-11 19:03:06 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core restart when convenient \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to perform a cold restart when all active calls have ended. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
ast_cli ( a - > fd , " Waiting for inactivity to perform restart \n " ) ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 2 /* really nicely */ , 1 /* safely */ , 1 /* restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_abort_shutdown ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core abort shutdown " ;
2007-10-11 19:03:06 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core abort shutdown \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to abort an executing shutdown or restart, and resume normal \n "
" call operations. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2002-05-14 14:43:52 +00:00
ast_cancel_shutdown ( ) ;
shuttingdown = 0 ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
1999-12-19 22:38:55 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_bang ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2003-10-22 03:46:36 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " ! " ;
e - > usage =
" Usage: !<command> \n "
" Executes a given shell command \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
return CLI_SUCCESS ;
2003-10-22 03:46:36 +00:00
}
2007-02-13 05:57:52 +00:00
static const char warranty_lines [ ] = {
" \n "
" NO WARRANTY \n "
" \n "
" BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY \n "
" FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN \n "
" OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES \n "
" PROVIDE THE PROGRAM \" AS IS \" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED \n "
" OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \n "
" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS \n "
" TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE \n "
" PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, \n "
" REPAIR OR CORRECTION. \n "
" \n "
" IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING \n "
" WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR \n "
" REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, \n "
" INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING \n "
" OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED \n "
" TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY \n "
" YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER \n "
" PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE \n "
" POSSIBILITY OF SUCH DAMAGES. \n "
2005-12-23 03:04:38 +00:00
} ;
2007-10-11 19:03:06 +00:00
static char * show_warranty ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2005-12-23 03:04:38 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show warranty " ;
e - > usage =
" Usage: core show warranty \n "
" Shows the warranty (if any) for this copy of Asterisk. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2005-12-23 03:04:38 +00:00
2008-11-02 18:52:13 +00:00
ast_cli ( a - > fd , " %s " , warranty_lines ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2005-12-23 03:04:38 +00:00
}
2007-02-13 05:57:52 +00:00
static const char license_lines [ ] = {
" \n "
" This program is free software; you can redistribute it and/or modify \n "
" it under the terms of the GNU General Public License version 2 as \n "
" published by the Free Software Foundation. \n "
" \n "
" This program also contains components licensed under other licenses. \n "
" They include: \n "
" \n "
" This program is distributed in the hope that it will be useful, \n "
" but WITHOUT ANY WARRANTY; without even the implied warranty of \n "
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n "
" GNU General Public License for more details. \n "
" \n "
" You should have received a copy of the GNU General Public License \n "
" along with this program; if not, write to the Free Software \n "
" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \n "
2005-12-23 03:04:38 +00:00
} ;
2007-10-11 19:03:06 +00:00
static char * show_license ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2005-12-23 03:04:38 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show license " ;
e - > usage =
" Usage: core show license \n "
" Shows the license(s) for this copy of Asterisk. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2005-12-23 03:04:38 +00:00
2008-11-02 18:52:13 +00:00
ast_cli ( a - > fd , " %s " , license_lines ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2005-12-23 03:04:38 +00:00
}
2003-10-22 03:46:36 +00:00
1999-12-19 22:38:55 +00:00
# define ASTERISK_PROMPT "*CLI> "
2001-05-09 03:11:22 +00:00
# define ASTERISK_PROMPT2 "%s*CLI> "
2006-09-18 19:54:18 +00:00
static struct ast_cli_entry cli_asterisk [ ] = {
2008-11-12 06:46:04 +00:00
AST_CLI_DEFINE ( handle_abort_shutdown , " Cancel a running shutdown " ) ,
AST_CLI_DEFINE ( handle_stop_now , " Shut down Asterisk immediately " ) ,
AST_CLI_DEFINE ( handle_stop_gracefully , " Gracefully shut down Asterisk " ) ,
AST_CLI_DEFINE ( handle_stop_when_convenient , " Shut down Asterisk at empty call volume " ) ,
AST_CLI_DEFINE ( handle_restart_now , " Restart Asterisk immediately " ) ,
AST_CLI_DEFINE ( handle_restart_gracefully , " Restart Asterisk gracefully " ) ,
AST_CLI_DEFINE ( handle_restart_when_convenient , " Restart Asterisk at empty call volume " ) ,
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( show_warranty , " Show the warranty (if any) for this copy of Asterisk " ) ,
AST_CLI_DEFINE ( show_license , " Show the license(s) for this copy of Asterisk " ) ,
AST_CLI_DEFINE ( handle_version , " Display version info " ) ,
AST_CLI_DEFINE ( handle_bang , " Execute a shell command " ) ,
2006-09-18 19:54:18 +00:00
# if !defined(LOW_MEMORY)
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_show_version_files , " List versions of files used to build Asterisk " ) ,
AST_CLI_DEFINE ( handle_show_threads , " Show running threads " ) ,
2008-12-16 20:08:34 +00:00
# if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_show_sysinfo , " Show System Information " ) ,
2007-04-11 20:59:08 +00:00
# endif
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_show_profile , " Display profiling info " ) ,
AST_CLI_DEFINE ( handle_show_settings , " Show some core settings " ) ,
AST_CLI_DEFINE ( handle_clear_profile , " Clear profiling info " ) ,
2005-06-07 16:07:06 +00:00
# endif /* ! LOW_MEMORY */
2005-06-03 03:04:08 +00:00
} ;
2001-05-09 03:11:22 +00:00
2008-08-10 19:35:50 +00:00
static int ast_el_read_char ( EditLine * editline , char * cp )
2003-02-06 06:15:25 +00:00
{
2006-03-31 00:33:28 +00:00
int num_read = 0 ;
int lastpos = 0 ;
2004-04-25 20:42:45 +00:00
struct pollfd fds [ 2 ] ;
2003-02-06 06:15:25 +00:00
int res ;
int max ;
2007-12-16 09:37:41 +00:00
# define EL_BUF_SIZE 512
char buf [ EL_BUF_SIZE ] ;
2003-02-06 06:15:25 +00:00
for ( ; ; ) {
2004-04-25 20:42:45 +00:00
max = 1 ;
fds [ 0 ] . fd = ast_consock ;
fds [ 0 ] . events = POLLIN ;
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_exec ) {
2004-04-25 20:42:45 +00:00
fds [ 1 ] . fd = STDIN_FILENO ;
fds [ 1 ] . events = POLLIN ;
max + + ;
2003-06-23 16:40:12 +00:00
}
2004-04-25 20:42:45 +00:00
res = poll ( fds , max , - 1 ) ;
2003-02-06 06:15:25 +00:00
if ( res < 0 ) {
2008-12-12 22:04:26 +00:00
if ( sig_flags . need_quit )
break ;
2003-02-06 06:15:25 +00:00
if ( errno = = EINTR )
continue ;
2004-04-25 20:42:45 +00:00
ast_log ( LOG_ERROR , " poll failed: %s \n " , strerror ( errno ) ) ;
2003-02-06 06:15:25 +00:00
break ;
}
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_exec & & fds [ 1 ] . revents ) {
2003-02-06 06:15:25 +00:00
num_read = read ( STDIN_FILENO , cp , 1 ) ;
if ( num_read < 1 ) {
break ;
} else
return ( num_read ) ;
}
2004-04-25 20:42:45 +00:00
if ( fds [ 0 ] . revents ) {
2008-05-22 18:54:41 +00:00
char * tmp ;
2003-02-06 06:15:25 +00:00
res = read ( ast_consock , buf , sizeof ( buf ) - 1 ) ;
/* if the remote side disappears exit */
if ( res < 1 ) {
fprintf ( stderr , " \n Disconnected from Asterisk server \n " ) ;
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_reconnect ) {
2004-06-25 14:39:38 +00:00
quit_handler ( 0 , 0 , 0 , 0 ) ;
} else {
int tries ;
2004-06-25 21:14:03 +00:00
int reconnects_per_second = 20 ;
fprintf ( stderr , " Attempting to reconnect for 30 seconds \n " ) ;
2008-02-11 18:27:47 +00:00
for ( tries = 0 ; tries < 30 * reconnects_per_second ; tries + + ) {
2004-06-25 14:39:38 +00:00
if ( ast_tryconnect ( ) ) {
2004-06-25 21:14:03 +00:00
fprintf ( stderr , " Reconnect succeeded after %.3f seconds \n " , 1.0 / reconnects_per_second * tries ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2004-06-25 21:14:03 +00:00
WELCOME_MESSAGE ;
2007-10-15 13:07:48 +00:00
if ( ! ast_opt_mute )
2008-05-27 18:59:06 +00:00
fdsend ( ast_consock , " logger mute silent " ) ;
2007-10-15 13:07:48 +00:00
else
printf ( " log and verbose output currently muted ('logger mute' to unmute) \n " ) ;
2004-06-25 14:39:38 +00:00
break ;
2006-10-29 20:47:01 +00:00
} else
2004-06-25 14:39:38 +00:00
usleep ( 1000000 / reconnects_per_second ) ;
}
2004-12-28 07:51:25 +00:00
if ( tries > = 30 * reconnects_per_second ) {
2004-06-25 14:39:38 +00:00
fprintf ( stderr , " Failed to reconnect for 30 seconds. Quitting. \n " ) ;
quit_handler ( 0 , 0 , 0 , 0 ) ;
}
}
2003-02-06 06:15:25 +00:00
}
buf [ res ] = ' \0 ' ;
2008-05-22 18:54:41 +00:00
/* Strip preamble from asynchronous events, too */
for ( tmp = buf ; * tmp ; tmp + + ) {
if ( * tmp = = 127 ) {
memmove ( tmp , tmp + 1 , strlen ( tmp ) ) ;
tmp - - ;
2009-01-21 21:03:40 +00:00
res - - ;
2008-05-22 18:54:41 +00:00
}
}
2008-05-05 23:00:31 +00:00
/* Write over the CLI prompt */
2008-11-02 18:52:13 +00:00
if ( ! ast_opt_exec & & ! lastpos ) {
if ( write ( STDOUT_FILENO , " \r " , 1 ) < 0 ) {
}
}
if ( write ( STDOUT_FILENO , buf , res ) < 0 ) {
}
2007-12-16 09:37:41 +00:00
if ( ( res < EL_BUF_SIZE - 1 ) & & ( ( buf [ res - 1 ] = = ' \n ' ) | | ( buf [ res - 2 ] = = ' \n ' ) ) ) {
2003-03-06 06:00:17 +00:00
* cp = CC_REFRESH ;
return ( 1 ) ;
2006-10-29 20:47:01 +00:00
} else
2003-02-06 06:15:25 +00:00
lastpos = 1 ;
}
}
* cp = ' \0 ' ;
return ( 0 ) ;
}
2008-07-30 15:30:18 +00:00
static struct ast_str * prompt = NULL ;
2008-08-10 19:35:50 +00:00
static char * cli_prompt ( EditLine * editline )
1999-12-19 22:38:55 +00:00
{
2008-07-30 15:30:18 +00:00
char tmp [ 100 ] ;
2004-03-26 04:59:41 +00:00
char * pfmt ;
2006-03-31 00:33:28 +00:00
int color_used = 0 ;
2008-07-30 15:30:18 +00:00
static int cli_prompt_changes = 0 ;
2004-05-02 19:13:16 +00:00
char term_code [ 20 ] ;
2008-07-30 15:30:18 +00:00
struct passwd * pw ;
struct group * gr ;
if ( prompt = = NULL ) {
prompt = ast_str_create ( 100 ) ;
} else if ( ! cli_prompt_changes ) {
2008-12-13 08:36:35 +00:00
return ast_str_buffer ( prompt ) ;
2008-07-30 15:30:18 +00:00
} else {
ast_str_reset ( prompt ) ;
}
2004-03-26 04:59:41 +00:00
if ( ( pfmt = getenv ( " ASTERISK_PROMPT " ) ) ) {
2008-07-30 15:30:18 +00:00
char * t = pfmt ;
struct timeval ts = ast_tvnow ( ) ;
while ( * t ! = ' \0 ' ) {
2004-03-26 04:59:41 +00:00
if ( * t = = ' % ' ) {
2008-07-30 15:30:18 +00:00
char hostname [ MAXHOSTNAMELEN ] = " " ;
int i , which ;
2007-07-18 19:47:20 +00:00
struct ast_tm tm = { 0 , } ;
2004-05-02 19:13:16 +00:00
int fgcolor = COLOR_WHITE , bgcolor = COLOR_BLACK ;
2004-03-26 04:59:41 +00:00
t + + ;
switch ( * t ) {
2006-03-31 00:33:28 +00:00
case ' C ' : /* color */
t + + ;
if ( sscanf ( t , " %d;%d%n " , & fgcolor , & bgcolor , & i ) = = 2 ) {
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %s " , term_color_code ( term_code , fgcolor , bgcolor , sizeof ( term_code ) ) ) ;
2006-03-31 00:33:28 +00:00
t + = i - 1 ;
} else if ( sscanf ( t , " %d%n " , & fgcolor , & i ) = = 1 ) {
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %s " , term_color_code ( term_code , fgcolor , 0 , sizeof ( term_code ) ) ) ;
2006-03-31 00:33:28 +00:00
t + = i - 1 ;
}
2004-05-02 19:13:16 +00:00
2006-03-31 00:33:28 +00:00
/* If the color has been reset correctly, then there's no need to reset it later */
2006-10-29 20:47:01 +00:00
color_used = ( ( fgcolor = = COLOR_WHITE ) & & ( bgcolor = = COLOR_BLACK ) ) ? 0 : 1 ;
2006-03-31 00:33:28 +00:00
break ;
case ' d ' : /* date */
2008-07-30 15:30:18 +00:00
if ( ast_localtime ( & ts , & tm , NULL ) ) {
ast_strftime ( tmp , sizeof ( tmp ) , " %Y-%m-%d " , & tm ) ;
ast_str_append ( & prompt , 0 , " %s " , tmp ) ;
cli_prompt_changes + + ;
}
break ;
case ' g ' : /* group */
if ( ( gr = getgrgid ( getgid ( ) ) ) ) {
ast_str_append ( & prompt , 0 , " %s " , gr - > gr_name ) ;
}
2006-03-31 00:33:28 +00:00
break ;
case ' h ' : /* hostname */
2008-07-30 15:30:18 +00:00
if ( ! gethostname ( hostname , sizeof ( hostname ) - 1 ) ) {
ast_str_append ( & prompt , 0 , " %s " , hostname ) ;
} else {
ast_str_append ( & prompt , 0 , " %s " , " localhost " ) ;
}
2006-03-31 00:33:28 +00:00
break ;
case ' H ' : /* short hostname */
if ( ! gethostname ( hostname , sizeof ( hostname ) - 1 ) ) {
2008-07-30 15:30:18 +00:00
char * dotptr ;
if ( ( dotptr = strchr ( hostname , ' . ' ) ) ) {
* dotptr = ' \0 ' ;
2004-05-02 19:13:16 +00:00
}
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %s " , hostname ) ;
} else {
ast_str_append ( & prompt , 0 , " %s " , " localhost " ) ;
}
2006-03-31 00:33:28 +00:00
break ;
2008-07-30 15:30:18 +00:00
# ifdef HAVE_GETLOADAVG
2006-03-31 00:33:28 +00:00
case ' l ' : /* load avg */
t + + ;
2008-07-30 15:30:18 +00:00
if ( sscanf ( t , " %d " , & which ) = = 1 & & which > 0 & & which < = 3 ) {
double list [ 3 ] ;
getloadavg ( list , 3 ) ;
ast_str_append ( & prompt , 0 , " %.2f " , list [ which - 1 ] ) ;
cli_prompt_changes + + ;
2006-03-31 00:33:28 +00:00
}
break ;
2004-03-26 04:59:41 +00:00
# endif
2006-05-11 13:54:00 +00:00
case ' s ' : /* Asterisk system name (from asterisk.conf) */
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %s " , ast_config_AST_SYSTEM_NAME ) ;
2006-05-11 13:54:00 +00:00
break ;
2006-03-31 00:33:28 +00:00
case ' t ' : /* time */
2008-07-30 15:30:18 +00:00
if ( ast_localtime ( & ts , & tm , NULL ) ) {
ast_strftime ( tmp , sizeof ( tmp ) , " %H:%M:%S " , & tm ) ;
ast_str_append ( & prompt , 0 , " %s " , tmp ) ;
cli_prompt_changes + + ;
}
break ;
case ' u ' : /* username */
if ( ( pw = getpwuid ( getuid ( ) ) ) ) {
ast_str_append ( & prompt , 0 , " %s " , pw - > pw_name ) ;
}
2006-03-31 00:33:28 +00:00
break ;
case ' # ' : /* process console or remote? */
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %c " , ast_opt_remote ? ' > ' : ' # ' ) ;
2006-03-31 00:33:28 +00:00
break ;
case ' % ' : /* literal % */
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %c " , ' % ' ) ;
2006-03-31 00:33:28 +00:00
break ;
case ' \0 ' : /* % is last character - prevent bug */
t - - ;
break ;
2004-03-26 04:59:41 +00:00
}
} else {
2008-12-13 08:36:35 +00:00
ast_str_append ( & prompt , 0 , " %c " , * t ) ;
2004-03-26 04:59:41 +00:00
}
2009-01-03 20:29:54 +00:00
t + + ;
2004-03-26 04:59:41 +00:00
}
2004-05-02 19:13:16 +00:00
if ( color_used ) {
/* Force colors back to normal at end */
2008-08-25 23:13:32 +00:00
ast_str_append ( & prompt , 0 , " %s " , term_color_code ( term_code , 0 , 0 , sizeof ( term_code ) ) ) ;
2004-05-02 19:13:16 +00:00
}
2008-07-30 15:30:18 +00:00
} else if ( remotehostname ) {
ast_str_set ( & prompt , 0 , ASTERISK_PROMPT2 , remotehostname ) ;
} else {
ast_str_set ( & prompt , 0 , " %s " , ASTERISK_PROMPT ) ;
}
2003-02-06 06:15:25 +00:00
2008-12-13 08:36:35 +00:00
return ast_str_buffer ( prompt ) ;
2003-02-06 06:15:25 +00:00
}
static char * * ast_el_strtoarr ( char * buf )
{
2007-12-12 17:15:56 +00:00
char * * match_list = NULL , * * match_list_tmp , * retstr ;
2004-06-29 04:42:19 +00:00
size_t match_list_len ;
2003-02-06 06:15:25 +00:00
int matches = 0 ;
2004-06-29 04:42:19 +00:00
match_list_len = 1 ;
2003-02-06 06:15:25 +00:00
while ( ( retstr = strsep ( & buf , " " ) ) ! = NULL ) {
2004-04-06 07:42:01 +00:00
if ( ! strcmp ( retstr , AST_CLI_COMPLETE_EOF ) )
break ;
2004-06-29 04:42:19 +00:00
if ( matches + 1 > = match_list_len ) {
match_list_len < < = 1 ;
2007-12-12 17:15:56 +00:00
if ( ( match_list_tmp = ast_realloc ( match_list , match_list_len * sizeof ( char * ) ) ) ) {
match_list = match_list_tmp ;
} else {
if ( match_list )
ast_free ( match_list ) ;
return ( char * * ) NULL ;
2006-02-14 22:28:01 +00:00
}
2003-02-06 06:15:25 +00:00
}
2007-06-14 23:01:01 +00:00
match_list [ matches + + ] = ast_strdup ( retstr ) ;
2003-02-06 06:15:25 +00:00
}
2004-06-29 04:42:19 +00:00
if ( ! match_list )
return ( char * * ) NULL ;
2003-02-06 06:15:25 +00:00
2006-02-14 22:28:01 +00:00
if ( matches > = match_list_len ) {
2007-12-12 17:15:56 +00:00
if ( ( match_list_tmp = ast_realloc ( match_list , ( match_list_len + 1 ) * sizeof ( char * ) ) ) ) {
match_list = match_list_tmp ;
} else {
if ( match_list )
ast_free ( match_list ) ;
return ( char * * ) NULL ;
2006-02-14 22:28:01 +00:00
}
}
2003-02-06 06:15:25 +00:00
match_list [ matches ] = ( char * ) NULL ;
return match_list ;
}
static int ast_el_sort_compare ( const void * i1 , const void * i2 )
{
char * s1 , * s2 ;
s1 = ( ( char * * ) i1 ) [ 0 ] ;
s2 = ( ( char * * ) i2 ) [ 0 ] ;
return strcasecmp ( s1 , s2 ) ;
}
static int ast_cli_display_match_list ( char * * matches , int len , int max )
{
int i , idx , limit , count ;
int screenwidth = 0 ;
int numoutput = 0 , numoutputline = 0 ;
screenwidth = ast_get_termcols ( STDOUT_FILENO ) ;
/* find out how many entries can be put on one line, with two spaces between strings */
limit = screenwidth / ( max + 2 ) ;
if ( limit = = 0 )
limit = 1 ;
/* how many lines of output */
count = len / limit ;
if ( count * limit < len )
count + + ;
idx = 1 ;
2006-01-07 15:17:10 +00:00
qsort ( & matches [ 0 ] , ( size_t ) ( len ) , sizeof ( char * ) , ast_el_sort_compare ) ;
2003-02-06 06:15:25 +00:00
for ( ; count > 0 ; count - - ) {
numoutputline = 0 ;
2008-02-11 18:27:47 +00:00
for ( i = 0 ; i < limit & & matches [ idx ] ; i + + , idx + + ) {
2003-02-06 06:15:25 +00:00
/* Don't print dupes */
if ( ( matches [ idx + 1 ] ! = NULL & & strcmp ( matches [ idx ] , matches [ idx + 1 ] ) = = 0 ) ) {
i - - ;
2007-06-06 21:20:11 +00:00
ast_free ( matches [ idx ] ) ;
2004-07-16 20:41:17 +00:00
matches [ idx ] = NULL ;
2003-02-06 06:15:25 +00:00
continue ;
}
2004-10-01 18:35:35 +00:00
numoutput + + ;
numoutputline + + ;
2003-02-06 06:15:25 +00:00
fprintf ( stdout , " %-*s " , max , matches [ idx ] ) ;
2007-06-06 21:20:11 +00:00
ast_free ( matches [ idx ] ) ;
2004-07-16 20:41:17 +00:00
matches [ idx ] = NULL ;
2003-02-06 06:15:25 +00:00
}
if ( numoutputline > 0 )
fprintf ( stdout , " \n " ) ;
}
return numoutput ;
1999-12-19 22:38:55 +00:00
}
2003-02-06 06:15:25 +00:00
2008-08-10 19:35:50 +00:00
static char * cli_complete ( EditLine * editline , int ch )
2001-05-09 03:11:22 +00:00
{
2006-03-31 00:33:28 +00:00
int len = 0 ;
2003-02-06 06:15:25 +00:00
char * ptr ;
int nummatches = 0 ;
char * * matches ;
int retval = CC_ERROR ;
2004-03-24 08:09:01 +00:00
char buf [ 2048 ] ;
2001-05-09 03:11:22 +00:00
int res ;
2003-02-06 06:15:25 +00:00
2008-08-10 19:35:50 +00:00
LineInfo * lf = ( LineInfo * ) el_line ( editline ) ;
2003-02-06 06:15:25 +00:00
2003-09-04 03:55:41 +00:00
* ( char * ) lf - > cursor = ' \0 ' ;
2003-02-21 06:00:08 +00:00
ptr = ( char * ) lf - > cursor ;
2003-02-06 06:15:25 +00:00
if ( ptr ) {
while ( ptr > lf - > buffer ) {
if ( isspace ( * ptr ) ) {
ptr + + ;
break ;
}
ptr - - ;
}
}
len = lf - > cursor - ptr ;
2005-12-04 20:40:46 +00:00
if ( ast_opt_remote ) {
2008-03-04 23:10:45 +00:00
snprintf ( buf , sizeof ( buf ) , " _COMMAND NUMMATCHES \" %s \" \" %s \" " , lf - > buffer , ptr ) ;
2008-05-27 18:59:06 +00:00
fdsend ( ast_consock , buf ) ;
2003-02-06 06:15:25 +00:00
res = read ( ast_consock , buf , sizeof ( buf ) ) ;
buf [ res ] = ' \0 ' ;
nummatches = atoi ( buf ) ;
if ( nummatches > 0 ) {
2004-04-06 07:42:01 +00:00
char * mbuf ;
int mlen = 0 , maxmbuf = 2048 ;
2006-02-14 22:28:01 +00:00
/* Start with a 2048 byte buffer */
if ( ! ( mbuf = ast_malloc ( maxmbuf ) ) )
2004-04-07 18:26:24 +00:00
return ( char * ) ( CC_ERROR ) ;
2008-03-04 23:10:45 +00:00
snprintf ( buf , sizeof ( buf ) , " _COMMAND MATCHESARRAY \" %s \" \" %s \" " , lf - > buffer , ptr ) ;
2008-05-27 18:59:06 +00:00
fdsend ( ast_consock , buf ) ;
2004-04-06 07:42:01 +00:00
res = 0 ;
2004-04-09 17:46:04 +00:00
mbuf [ 0 ] = ' \0 ' ;
2004-04-06 07:42:01 +00:00
while ( ! strstr ( mbuf , AST_CLI_COMPLETE_EOF ) & & res ! = - 1 ) {
if ( mlen + 1024 > maxmbuf ) {
/* Every step increment buffer 1024 bytes */
2006-02-14 22:28:01 +00:00
maxmbuf + = 1024 ;
if ( ! ( mbuf = ast_realloc ( mbuf , maxmbuf ) ) )
2004-04-07 18:26:24 +00:00
return ( char * ) ( CC_ERROR ) ;
2004-04-06 07:42:01 +00:00
}
/* Only read 1024 bytes at a time */
res = read ( ast_consock , mbuf + mlen , 1024 ) ;
if ( res > 0 )
mlen + = res ;
}
mbuf [ mlen ] = ' \0 ' ;
2003-02-06 06:15:25 +00:00
2004-04-06 07:42:01 +00:00
matches = ast_el_strtoarr ( mbuf ) ;
2007-06-06 21:20:11 +00:00
ast_free ( mbuf ) ;
2003-02-06 06:15:25 +00:00
} else
matches = ( char * * ) NULL ;
2004-10-01 18:35:35 +00:00
} else {
2006-01-07 15:17:10 +00:00
char * * p , * oldbuf = NULL ;
nummatches = 0 ;
2003-02-06 06:15:25 +00:00
matches = ast_cli_completion_matches ( ( char * ) lf - > buffer , ptr ) ;
2006-01-07 15:17:10 +00:00
for ( p = matches ; p & & * p ; p + + ) {
if ( ! oldbuf | | strcmp ( * p , oldbuf ) )
nummatches + + ;
oldbuf = * p ;
}
2003-02-06 06:15:25 +00:00
}
if ( matches ) {
int i ;
int matches_num , maxlen , match_len ;
if ( matches [ 0 ] [ 0 ] ! = ' \0 ' ) {
2008-08-10 19:35:50 +00:00
el_deletestr ( editline , ( int ) len ) ;
el_insertstr ( editline , matches [ 0 ] ) ;
2003-02-06 06:15:25 +00:00
retval = CC_REFRESH ;
}
if ( nummatches = = 1 ) {
/* Found an exact match */
2008-08-10 19:35:50 +00:00
el_insertstr ( editline , " " ) ;
2003-02-06 06:15:25 +00:00
retval = CC_REFRESH ;
} else {
/* Must be more than one match */
2008-02-11 18:27:47 +00:00
for ( i = 1 , maxlen = 0 ; matches [ i ] ; i + + ) {
2003-02-06 06:15:25 +00:00
match_len = strlen ( matches [ i ] ) ;
if ( match_len > maxlen )
maxlen = match_len ;
}
matches_num = i - 1 ;
if ( matches_num > 1 ) {
fprintf ( stdout , " \n " ) ;
ast_cli_display_match_list ( matches , nummatches , maxlen ) ;
retval = CC_REDISPLAY ;
} else {
2008-08-10 19:35:50 +00:00
el_insertstr ( editline , " " ) ;
2003-02-06 06:15:25 +00:00
retval = CC_REFRESH ;
}
}
2007-01-19 17:02:36 +00:00
for ( i = 0 ; matches [ i ] ; i + + )
2007-06-06 21:20:11 +00:00
ast_free ( matches [ i ] ) ;
ast_free ( matches ) ;
2003-02-06 06:15:25 +00:00
}
2004-06-13 21:25:10 +00:00
return ( char * ) ( long ) retval ;
2003-02-06 06:15:25 +00:00
}
static int ast_el_initialize ( void )
{
HistEvent ev ;
2004-07-31 02:23:27 +00:00
char * editor = getenv ( " AST_EDITOR " ) ;
2003-02-06 06:15:25 +00:00
if ( el ! = NULL )
el_end ( el ) ;
if ( el_hist ! = NULL )
history_end ( el_hist ) ;
el = el_init ( " asterisk " , stdin , stdout , stderr ) ;
el_set ( el , EL_PROMPT , cli_prompt ) ;
el_set ( el , EL_EDITMODE , 1 ) ;
2004-07-30 18:30:48 +00:00
el_set ( el , EL_EDITOR , editor ? editor : " emacs " ) ;
2003-02-06 06:15:25 +00:00
el_hist = history_init ( ) ;
if ( ! el | | ! el_hist )
return - 1 ;
/* setup history with 100 entries */
history ( el_hist , & ev , H_SETSIZE , 100 ) ;
el_set ( el , EL_HIST , history , el_hist ) ;
el_set ( el , EL_ADDFN , " ed-complete " , " Complete argument " , cli_complete ) ;
/* Bind <tab> to command completion */
el_set ( el , EL_BIND , " ^I " , " ed-complete " , NULL ) ;
/* Bind ? to command completion */
el_set ( el , EL_BIND , " ? " , " ed-complete " , NULL ) ;
2004-03-29 04:12:13 +00:00
/* Bind ^D to redisplay */
el_set ( el , EL_BIND , " ^D " , " ed-redisplay " , NULL ) ;
2003-02-06 06:15:25 +00:00
return 0 ;
}
2008-10-04 16:20:31 +00:00
# define MAX_HISTORY_COMMAND_LENGTH 256
2003-02-06 06:15:25 +00:00
static int ast_el_add_history ( char * buf )
{
HistEvent ev ;
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
2008-10-04 16:20:31 +00:00
if ( strlen ( buf ) > ( MAX_HISTORY_COMMAND_LENGTH - 1 ) )
2004-01-23 19:12:44 +00:00
return 0 ;
2008-10-04 16:20:31 +00:00
return ( history ( el_hist , & ev , H_ENTER , ast_strip ( ast_strdupa ( buf ) ) ) ) ;
2003-02-06 06:15:25 +00:00
}
static int ast_el_write_history ( char * filename )
{
HistEvent ev ;
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
return ( history ( el_hist , & ev , H_SAVE , filename ) ) ;
}
static int ast_el_read_history ( char * filename )
{
2008-10-04 16:20:31 +00:00
char buf [ MAX_HISTORY_COMMAND_LENGTH ] ;
2003-02-06 06:15:25 +00:00
FILE * f ;
int ret = - 1 ;
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
if ( ( f = fopen ( filename , " r " ) ) = = NULL )
return ret ;
while ( ! feof ( f ) ) {
2008-10-04 16:20:31 +00:00
if ( ! fgets ( buf , sizeof ( buf ) , f ) )
break ;
2003-02-06 06:15:25 +00:00
if ( ! strcmp ( buf , " _HiStOrY_V2_ \n " ) )
continue ;
2004-08-03 06:31:20 +00:00
if ( ast_all_zeros ( buf ) )
continue ;
2003-02-06 06:15:25 +00:00
if ( ( ret = ast_el_add_history ( buf ) ) = = - 1 )
break ;
}
fclose ( f ) ;
return ret ;
2001-05-09 03:11:22 +00:00
}
2008-11-02 18:52:13 +00:00
static void ast_remotecontrol ( char * data )
2001-05-09 03:11:22 +00:00
{
char buf [ 80 ] ;
int res ;
char filename [ 80 ] = " " ;
char * hostname ;
char * cpid ;
char * version ;
int pid ;
2006-03-31 00:33:28 +00:00
char * stringp = NULL ;
2003-02-06 06:15:25 +00:00
char * ebuf ;
int num = 0 ;
2008-12-11 23:38:56 +00:00
memset ( & sig_flags , 0 , sizeof ( sig_flags ) ) ;
signal ( SIGINT , __remote_quit_handler ) ;
signal ( SIGTERM , __remote_quit_handler ) ;
signal ( SIGHUP , __remote_quit_handler ) ;
2008-11-02 18:52:13 +00:00
if ( read ( ast_consock , buf , sizeof ( buf ) ) < 0 ) {
ast_log ( LOG_ERROR , " read() failed: %s \n " , strerror ( errno ) ) ;
return ;
}
2008-07-08 20:17:08 +00:00
if ( data ) {
char prefix [ ] = " cli quit after " ;
char * tmp = alloca ( strlen ( data ) + strlen ( prefix ) + 1 ) ;
sprintf ( tmp , " %s%s " , prefix , data ) ;
2008-11-02 18:52:13 +00:00
if ( write ( ast_consock , tmp , strlen ( tmp ) + 1 ) < 0 ) {
ast_log ( LOG_ERROR , " write() failed: %s \n " , strerror ( errno ) ) ;
2008-12-11 23:38:56 +00:00
if ( sig_flags . need_quit = = 1 ) {
return ;
}
2008-11-02 18:52:13 +00:00
}
2008-07-08 20:17:08 +00:00
}
2006-03-31 00:33:28 +00:00
stringp = buf ;
2003-02-06 06:15:25 +00:00
hostname = strsep ( & stringp , " / " ) ;
cpid = strsep ( & stringp , " / " ) ;
2003-09-05 04:36:58 +00:00
version = strsep ( & stringp , " \n " ) ;
2001-05-09 03:11:22 +00:00
if ( ! version )
version = " <Version Unknown> " ;
2006-03-31 00:33:28 +00:00
stringp = hostname ;
2003-02-06 06:15:25 +00:00
strsep ( & stringp , " . " ) ;
2001-05-09 03:11:22 +00:00
if ( cpid )
pid = atoi ( cpid ) ;
else
pid = - 1 ;
2007-10-13 05:53:19 +00:00
if ( ! data ) {
2008-08-10 19:35:50 +00:00
char tmp [ 80 ] ;
2007-10-13 05:53:19 +00:00
snprintf ( tmp , sizeof ( tmp ) , " core set verbose atleast %d " , option_verbose ) ;
2008-05-27 18:59:06 +00:00
fdsend ( ast_consock , tmp ) ;
2007-10-13 05:53:19 +00:00
snprintf ( tmp , sizeof ( tmp ) , " core set debug atleast %d " , option_debug ) ;
2008-05-27 18:59:06 +00:00
fdsend ( ast_consock , tmp ) ;
2007-10-13 05:53:19 +00:00
if ( ! ast_opt_mute )
2008-05-27 18:59:06 +00:00
fdsend ( ast_consock , " logger mute silent " ) ;
2007-10-13 05:53:19 +00:00
else
printf ( " log and verbose output currently muted ('logger mute' to unmute) \n " ) ;
2006-05-26 19:48:17 +00:00
}
2003-02-06 06:15:25 +00:00
2005-12-04 20:40:46 +00:00
if ( ast_opt_exec & & data ) { /* hack to print output then exit if asterisk -rx is used */
2006-06-13 03:56:09 +00:00
struct pollfd fds ;
fds . fd = ast_consock ;
fds . events = POLLIN ;
fds . revents = 0 ;
2008-05-05 23:00:31 +00:00
while ( poll ( & fds , 1 , 500 ) > 0 ) {
2008-08-10 19:35:50 +00:00
char buffer [ 512 ] = " " , * curline = buffer , * nextline ;
2008-05-05 23:00:31 +00:00
int not_written = 1 ;
2008-12-11 23:38:56 +00:00
if ( sig_flags . need_quit = = 1 ) {
break ;
}
2008-08-10 19:35:50 +00:00
if ( read ( ast_consock , buffer , sizeof ( buffer ) - 1 ) < = 0 ) {
2008-05-05 23:00:31 +00:00
break ;
}
do {
if ( ( nextline = strchr ( curline , ' \n ' ) ) ) {
nextline + + ;
} else {
nextline = strchr ( curline , ' \0 ' ) ;
}
/* Skip verbose lines */
if ( * curline ! = 127 ) {
not_written = 0 ;
2008-11-02 18:52:13 +00:00
if ( write ( STDOUT_FILENO , curline , nextline - curline ) < 0 ) {
ast_log ( LOG_WARNING , " write() failed: %s \n " , strerror ( errno ) ) ;
}
2008-05-05 23:00:31 +00:00
}
curline = nextline ;
} while ( ! ast_strlen_zero ( curline ) ) ;
/* No non-verbose output in 500ms */
if ( not_written ) {
break ;
}
}
2003-06-23 16:40:12 +00:00
return ;
}
2008-11-05 22:19:18 +00:00
ast_verbose ( " Connected to Asterisk %s currently running on %s (pid = %d) \n " , version , hostname , pid ) ;
remotehostname = hostname ;
if ( getenv ( " HOME " ) )
snprintf ( filename , sizeof ( filename ) , " %s/.asterisk_history " , getenv ( " HOME " ) ) ;
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
el_set ( el , EL_GETCFN , ast_el_read_char ) ;
if ( ! ast_strlen_zero ( filename ) )
ast_el_read_history ( filename ) ;
2006-03-31 00:33:28 +00:00
for ( ; ; ) {
2003-02-06 06:15:25 +00:00
ebuf = ( char * ) el_gets ( el , & num ) ;
2008-12-11 23:38:56 +00:00
if ( sig_flags . need_quit = = 1 ) {
break ;
}
2007-06-27 23:30:31 +00:00
if ( ! ebuf & & write ( 1 , " " , 1 ) < 0 )
break ;
2005-10-26 18:54:24 +00:00
if ( ! ast_strlen_zero ( ebuf ) ) {
2003-02-06 06:15:25 +00:00
if ( ebuf [ strlen ( ebuf ) - 1 ] = = ' \n ' )
ebuf [ strlen ( ebuf ) - 1 ] = ' \0 ' ;
if ( ! remoteconsolehandler ( ebuf ) ) {
2008-05-21 18:43:26 +00:00
/* Strip preamble from output */
2008-08-10 19:35:50 +00:00
char * temp ;
for ( temp = ebuf ; * temp ; temp + + ) {
if ( * temp = = 127 ) {
memmove ( temp , temp + 1 , strlen ( temp ) ) ;
temp - - ;
2008-05-21 18:43:26 +00:00
}
}
2003-02-06 06:15:25 +00:00
res = write ( ast_consock , ebuf , strlen ( ebuf ) + 1 ) ;
2001-05-09 03:11:22 +00:00
if ( res < 1 ) {
ast_log ( LOG_WARNING , " Unable to write: %s \n " , strerror ( errno ) ) ;
break ;
}
}
}
}
printf ( " \n Disconnected from Asterisk server \n " ) ;
}
2004-07-18 17:58:05 +00:00
static int show_version ( void )
{
Now that the version.h file was getting properly regenerated every time the svn
revision changed, every module that used the version was getting rebuilt after
every svn update. This severly annoyed me pretty quickly, so I have improved
the situation.
Now, instead of generating version.h, main/version.c is generated. version.c
includes the version information, as well as a couple of API calls for modules
to retrieve the version. So now, only version.c will get rebuilt, and the main
asterisk binary relinked, which is must faster than rebuilding http.c, manager.c,
asterisk.c, relinking the asterisk binary, chan_sip.c, func_version.c, res_agi ...
The only minor change in behavior here is that the version information reported by
chan_sip, for example, is the version of the Asterisk core, and not necessarily the
Asterisk version that the chan_sip module came from.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@96717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-01-05 22:09:06 +00:00
printf ( " Asterisk %s \n " , ast_get_version ( ) ) ;
2004-07-18 17:58:05 +00:00
return 0 ;
}
2003-02-06 06:15:25 +00:00
static int show_cli_help ( void ) {
2008-01-24 17:24:08 +00:00
printf ( " Asterisk %s, Copyright (C) 1999 - 2008, Digium, Inc. and others. \n " , ast_get_version ( ) ) ;
2002-09-12 03:22:07 +00:00
printf ( " Usage: asterisk [OPTIONS] \n " ) ;
printf ( " Valid Options: \n " ) ;
2004-07-18 17:58:05 +00:00
printf ( " -V Display version number and exit \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -C <configfile> Use an alternate configuration file \n " ) ;
2004-07-18 16:20:54 +00:00
printf ( " -G <group> Run as a group other than the caller \n " ) ;
printf ( " -U <user> Run as a user other than the caller \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -c Provide console CLI \n " ) ;
printf ( " -d Enable extra debugging \n " ) ;
2006-08-21 20:12:18 +00:00
# if HAVE_WORKING_FORK
2004-05-13 19:57:45 +00:00
printf ( " -f Do not fork \n " ) ;
2006-08-21 20:12:18 +00:00
printf ( " -F Always fork \n " ) ;
# endif
2004-05-13 19:57:45 +00:00
printf ( " -g Dump core in case of a crash \n " ) ;
printf ( " -h This help screen \n " ) ;
2004-12-28 07:51:25 +00:00
printf ( " -i Initialize crypto keys at startup \n " ) ;
2008-06-12 17:27:55 +00:00
printf ( " -I Enable internal timing if DAHDI timer is available \n " ) ;
2006-03-31 00:33:28 +00:00
printf ( " -L <load> Limit the maximum load average before rejecting new calls \n " ) ;
printf ( " -M <value> Limit the maximum number of calls to the specified value \n " ) ;
2007-09-12 15:19:11 +00:00
printf ( " -m Mute debugging and console output on the console \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -n Disable console colorization \n " ) ;
printf ( " -p Run as pseudo-realtime thread \n " ) ;
2004-12-28 07:51:25 +00:00
printf ( " -q Quiet mode (suppress output) \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -r Connect to Asterisk on this machine \n " ) ;
2007-09-12 15:19:11 +00:00
printf ( " -R Same as -r, except attempt to reconnect if disconnected \n " ) ;
2008-08-25 23:13:32 +00:00
printf ( " -s <socket> Connect to Asterisk via socket <socket> (only valid with -r) \n " ) ;
2007-09-12 15:19:11 +00:00
printf ( " -t Record soundfiles in /var/tmp and move them where they \n " ) ;
printf ( " belong after they are done \n " ) ;
printf ( " -T Display the time in [Mmm dd hh:mm:ss] format for each line \n " ) ;
printf ( " of output to the CLI \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -v Increase verbosity (multiple v's = more verbose) \n " ) ;
printf ( " -x <cmd> Execute command <cmd> (only valid with -r) \n " ) ;
2008-08-25 23:13:32 +00:00
printf ( " -W Adjust terminal colors to compensate for a light background \n " ) ;
2002-09-12 03:22:07 +00:00
printf ( " \n " ) ;
return 0 ;
}
2006-03-25 23:50:09 +00:00
static void ast_readconfig ( void )
{
2003-02-06 06:15:25 +00:00
struct ast_config * cfg ;
struct ast_variable * v ;
2007-12-18 09:26:03 +00:00
char * config = DEFAULT_CONFIG_FILE ;
2007-05-11 19:56:57 +00:00
char hostname [ MAXHOSTNAMELEN ] = " " ;
2007-08-16 21:09:46 +00:00
struct ast_flags config_flags = { 0 } ;
2007-09-24 22:06:19 +00:00
struct {
unsigned int dbdir : 1 ;
unsigned int keydir : 1 ;
} found = { 0 , 0 } ;
2003-02-06 06:15:25 +00:00
2005-12-04 20:40:46 +00:00
if ( ast_opt_override_config ) {
2008-03-26 18:39:06 +00:00
cfg = ast_config_load2 ( ast_config_AST_CONFIG_FILE , " " /* core, can't reload */ , config_flags ) ;
2008-09-12 23:30:03 +00:00
if ( cfg = = CONFIG_STATUS_FILEMISSING | | cfg = = CONFIG_STATUS_FILEUNCHANGED | | cfg = = CONFIG_STATUS_FILEINVALID )
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to open specified master config file '%s', using built-in defaults \n " , ast_config_AST_CONFIG_FILE ) ;
2006-10-29 20:47:01 +00:00
} else
2008-03-26 18:39:06 +00:00
cfg = ast_config_load2 ( config , " " /* core, can't reload */ , config_flags ) ;
2003-02-06 06:15:25 +00:00
/* init with buildtime config */
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . config_dir , DEFAULT_CONFIG_DIR , sizeof ( cfg_paths . config_dir ) ) ;
ast_copy_string ( cfg_paths . spool_dir , DEFAULT_SPOOL_DIR , sizeof ( cfg_paths . spool_dir ) ) ;
ast_copy_string ( cfg_paths . module_dir , DEFAULT_MODULE_DIR , sizeof ( cfg_paths . module_dir ) ) ;
2008-03-04 23:10:45 +00:00
snprintf ( cfg_paths . monitor_dir , sizeof ( cfg_paths . monitor_dir ) , " %s/monitor " , cfg_paths . spool_dir ) ;
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . var_dir , DEFAULT_VAR_DIR , sizeof ( cfg_paths . var_dir ) ) ;
ast_copy_string ( cfg_paths . data_dir , DEFAULT_DATA_DIR , sizeof ( cfg_paths . data_dir ) ) ;
ast_copy_string ( cfg_paths . log_dir , DEFAULT_LOG_DIR , sizeof ( cfg_paths . log_dir ) ) ;
ast_copy_string ( cfg_paths . agi_dir , DEFAULT_AGI_DIR , sizeof ( cfg_paths . agi_dir ) ) ;
ast_copy_string ( cfg_paths . db_path , DEFAULT_DB , sizeof ( cfg_paths . db_path ) ) ;
ast_copy_string ( cfg_paths . key_dir , DEFAULT_KEY_DIR , sizeof ( cfg_paths . key_dir ) ) ;
ast_copy_string ( cfg_paths . pid_path , DEFAULT_PID , sizeof ( cfg_paths . pid_path ) ) ;
ast_copy_string ( cfg_paths . socket_path , DEFAULT_SOCKET , sizeof ( cfg_paths . socket_path ) ) ;
ast_copy_string ( cfg_paths . run_dir , DEFAULT_RUN_DIR , sizeof ( cfg_paths . run_dir ) ) ;
2005-07-25 23:09:13 +00:00
2008-06-10 12:48:50 +00:00
ast_set_default_eid ( & g_eid ) ;
2003-02-06 06:15:25 +00:00
/* no asterisk.conf? no problem, use buildtime config! */
2008-09-12 23:30:03 +00:00
if ( cfg = = CONFIG_STATUS_FILEMISSING | | cfg = = CONFIG_STATUS_FILEUNCHANGED | | cfg = = CONFIG_STATUS_FILEINVALID ) {
2004-09-07 14:36:56 +00:00
return ;
2003-02-06 06:15:25 +00:00
}
2006-05-30 21:37:11 +00:00
for ( v = ast_variable_browse ( cfg , " files " ) ; v ; v = v - > next ) {
2006-10-29 20:47:01 +00:00
if ( ! strcasecmp ( v - > name , " astctlpermissions " ) )
2007-12-20 09:55:05 +00:00
ast_copy_string ( ast_config_AST_CTL_PERMISSIONS , v - > value , sizeof ( ast_config_AST_CTL_PERMISSIONS ) ) ;
2006-10-29 20:47:01 +00:00
else if ( ! strcasecmp ( v - > name , " astctlowner " ) )
2007-12-20 09:55:05 +00:00
ast_copy_string ( ast_config_AST_CTL_OWNER , v - > value , sizeof ( ast_config_AST_CTL_OWNER ) ) ;
2006-10-29 20:47:01 +00:00
else if ( ! strcasecmp ( v - > name , " astctlgroup " ) )
2007-12-20 09:55:05 +00:00
ast_copy_string ( ast_config_AST_CTL_GROUP , v - > value , sizeof ( ast_config_AST_CTL_GROUP ) ) ;
2006-10-29 20:47:01 +00:00
else if ( ! strcasecmp ( v - > name , " astctl " ) )
2007-12-20 09:55:05 +00:00
ast_copy_string ( ast_config_AST_CTL , v - > value , sizeof ( ast_config_AST_CTL ) ) ;
2005-02-11 21:16:34 +00:00
}
2006-05-30 21:37:11 +00:00
for ( v = ast_variable_browse ( cfg , " directories " ) ; v ; v = v - > next ) {
2003-02-06 06:15:25 +00:00
if ( ! strcasecmp ( v - > name , " astetcdir " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . config_dir , v - > value , sizeof ( cfg_paths . config_dir ) ) ;
2003-02-06 06:15:25 +00:00
} else if ( ! strcasecmp ( v - > name , " astspooldir " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . spool_dir , v - > value , sizeof ( cfg_paths . spool_dir ) ) ;
2008-03-04 23:10:45 +00:00
snprintf ( cfg_paths . monitor_dir , sizeof ( cfg_paths . monitor_dir ) , " %s/monitor " , v - > value ) ;
2003-02-06 06:15:25 +00:00
} else if ( ! strcasecmp ( v - > name , " astvarlibdir " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . var_dir , v - > value , sizeof ( cfg_paths . var_dir ) ) ;
2007-09-24 22:06:19 +00:00
if ( ! found . dbdir )
2007-12-20 09:55:05 +00:00
snprintf ( cfg_paths . db_path , sizeof ( cfg_paths . db_path ) , " %s/astdb " , v - > value ) ;
2007-09-24 22:06:19 +00:00
} else if ( ! strcasecmp ( v - > name , " astdbdir " ) ) {
2007-12-20 09:55:05 +00:00
snprintf ( cfg_paths . db_path , sizeof ( cfg_paths . db_path ) , " %s/astdb " , v - > value ) ;
2007-09-24 22:06:19 +00:00
found . dbdir = 1 ;
2006-04-15 22:53:53 +00:00
} else if ( ! strcasecmp ( v - > name , " astdatadir " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . data_dir , v - > value , sizeof ( cfg_paths . data_dir ) ) ;
2007-09-24 22:06:19 +00:00
if ( ! found . keydir )
2007-12-20 09:55:05 +00:00
snprintf ( cfg_paths . key_dir , sizeof ( cfg_paths . key_dir ) , " %s/keys " , v - > value ) ;
2007-09-24 22:06:19 +00:00
} else if ( ! strcasecmp ( v - > name , " astkeydir " ) ) {
2007-12-20 09:55:05 +00:00
snprintf ( cfg_paths . key_dir , sizeof ( cfg_paths . key_dir ) , " %s/keys " , v - > value ) ;
2007-09-24 22:06:19 +00:00
found . keydir = 1 ;
2003-02-06 06:15:25 +00:00
} else if ( ! strcasecmp ( v - > name , " astlogdir " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . log_dir , v - > value , sizeof ( cfg_paths . log_dir ) ) ;
2003-02-06 06:15:25 +00:00
} else if ( ! strcasecmp ( v - > name , " astagidir " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . agi_dir , v - > value , sizeof ( cfg_paths . agi_dir ) ) ;
2003-02-06 06:15:25 +00:00
} else if ( ! strcasecmp ( v - > name , " astrundir " ) ) {
2007-12-20 09:55:05 +00:00
snprintf ( cfg_paths . pid_path , sizeof ( cfg_paths . pid_path ) , " %s/%s " , v - > value , " asterisk.pid " ) ;
snprintf ( cfg_paths . socket_path , sizeof ( cfg_paths . socket_path ) , " %s/%s " , v - > value , ast_config_AST_CTL ) ;
ast_copy_string ( cfg_paths . run_dir , v - > value , sizeof ( cfg_paths . run_dir ) ) ;
2003-02-06 06:15:25 +00:00
} else if ( ! strcasecmp ( v - > name , " astmoddir " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . module_dir , v - > value , sizeof ( cfg_paths . module_dir ) ) ;
2003-02-06 06:15:25 +00:00
}
}
2006-05-30 21:37:11 +00:00
for ( v = ast_variable_browse ( cfg , " options " ) ; v ; v = v - > next ) {
2005-02-09 00:13:52 +00:00
/* verbose level (-v at startup) */
2004-10-01 18:35:35 +00:00
if ( ! strcasecmp ( v - > name , " verbose " ) ) {
2005-07-25 23:09:13 +00:00
option_verbose = atoi ( v - > value ) ;
2006-07-28 19:17:56 +00:00
/* whether or not to force timestamping in CLI verbose output. (-T at startup) */
2005-03-11 07:24:10 +00:00
} else if ( ! strcasecmp ( v - > name , " timestamp " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_TIMESTAMP ) ;
2005-02-09 00:13:52 +00:00
/* whether or not to support #exec in config files */
2005-02-02 03:38:24 +00:00
} else if ( ! strcasecmp ( v - > name , " execincludes " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_EXEC_INCLUDES ) ;
2005-02-09 21:17:34 +00:00
/* debug level (-d at startup) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " debug " ) ) {
2005-02-09 00:13:52 +00:00
option_debug = 0 ;
if ( sscanf ( v - > value , " %d " , & option_debug ) ! = 1 ) {
option_debug = ast_true ( v - > value ) ;
}
2006-08-21 20:12:18 +00:00
# if HAVE_WORKING_FORK
2005-02-09 00:13:52 +00:00
/* Disable forking (-f at startup) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " nofork " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_NO_FORK ) ;
2006-04-30 14:55:05 +00:00
/* Always fork, even if verbose or debug are enabled (-F at startup) */
} else if ( ! strcasecmp ( v - > name , " alwaysfork " ) ) {
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_ALWAYS_FORK ) ;
2006-08-21 20:12:18 +00:00
# endif
2005-02-09 00:13:52 +00:00
/* Run quietly (-q at startup ) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " quiet " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_QUIET ) ;
2005-02-09 00:13:52 +00:00
/* Run as console (-c at startup, implies nofork) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " console " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_CONSOLE ) ;
2006-01-16 17:37:44 +00:00
/* Run with high priority if the O/S permits (-p at startup) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " highpriority " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_HIGH_PRIORITY ) ;
2005-02-09 00:13:52 +00:00
/* Initialize RSA auth keys (IAX2) (-i at startup) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " initcrypto " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_INIT_KEYS ) ;
2005-02-09 00:13:52 +00:00
/* Disable ANSI colors for console (-c at startup) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " nocolor " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_NO_COLOR ) ;
2005-05-19 01:57:19 +00:00
/* Disable some usage warnings for picky people :p */
} else if ( ! strcasecmp ( v - > name , " dontwarn " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_DONT_WARN ) ;
2005-02-09 00:13:52 +00:00
/* Dump core in case of crash (-g) */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " dumpcore " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_DUMP_CORE ) ;
2005-02-09 00:13:52 +00:00
/* Cache recorded sound files to another directory during recording */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " cache_record_files " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_CACHE_RECORD_FILES ) ;
2005-02-09 00:13:52 +00:00
/* Specify cache directory */
2004-09-07 01:49:08 +00:00
} else if ( ! strcasecmp ( v - > name , " record_cache_dir " ) ) {
2005-07-25 23:09:13 +00:00
ast_copy_string ( record_cache_dir , v - > value , AST_CACHE_DIR_LEN ) ;
2005-04-04 03:28:38 +00:00
/* Build transcode paths via SLINEAR, instead of directly */
} else if ( ! strcasecmp ( v - > name , " transcode_via_sln " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_TRANSCODE_VIA_SLIN ) ;
2008-03-25 14:39:45 +00:00
/* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
} else if ( ! strcasecmp ( v - > name , " transmit_silence_during_record " ) | | ! strcasecmp ( v - > name , " transmit_silence " ) ) {
2005-12-04 20:40:46 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_TRANSMIT_SILENCE ) ;
2006-03-30 06:07:04 +00:00
/* Enable internal timing */
} else if ( ! strcasecmp ( v - > name , " internal_timing " ) ) {
2006-03-30 06:26:16 +00:00
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_INTERNAL_TIMING ) ;
2005-05-18 01:49:13 +00:00
} else if ( ! strcasecmp ( v - > name , " maxcalls " ) ) {
2005-07-25 23:09:13 +00:00
if ( ( sscanf ( v - > value , " %d " , & option_maxcalls ) ! = 1 ) | | ( option_maxcalls < 0 ) ) {
2005-05-18 01:49:13 +00:00
option_maxcalls = 0 ;
}
2005-10-26 03:58:32 +00:00
} else if ( ! strcasecmp ( v - > name , " maxload " ) ) {
2005-10-31 21:25:21 +00:00
double test [ 1 ] ;
if ( getloadavg ( test , 1 ) = = - 1 ) {
ast_log ( LOG_ERROR , " Cannot obtain load average on this system. 'maxload' option disabled. \n " ) ;
option_maxload = 0.0 ;
} else if ( ( sscanf ( v - > value , " %lf " , & option_maxload ) ! = 1 ) | | ( option_maxload < 0.0 ) ) {
2005-10-26 03:58:32 +00:00
option_maxload = 0.0 ;
}
2006-11-22 17:41:07 +00:00
/* Set the maximum amount of open files */
} else if ( ! strcasecmp ( v - > name , " maxfiles " ) ) {
2007-02-14 20:22:20 +00:00
option_maxfiles = atoi ( v - > value ) ;
set_ulimit ( option_maxfiles ) ;
2005-11-08 00:30:29 +00:00
/* What user to run as */
} else if ( ! strcasecmp ( v - > name , " runuser " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . run_user , v - > value , sizeof ( cfg_paths . run_user ) ) ;
2005-11-08 00:30:29 +00:00
/* What group to run as */
} else if ( ! strcasecmp ( v - > name , " rungroup " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . run_group , v - > value , sizeof ( cfg_paths . run_group ) ) ;
2006-02-14 23:42:36 +00:00
} else if ( ! strcasecmp ( v - > name , " systemname " ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . system_name , v - > value , sizeof ( cfg_paths . system_name ) ) ;
2007-05-11 19:56:57 +00:00
} else if ( ! strcasecmp ( v - > name , " autosystemname " ) ) {
if ( ast_true ( v - > value ) ) {
if ( ! gethostname ( hostname , sizeof ( hostname ) - 1 ) )
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . system_name , hostname , sizeof ( cfg_paths . system_name ) ) ;
2007-05-11 19:56:57 +00:00
else {
2007-05-11 21:16:39 +00:00
if ( ast_strlen_zero ( ast_config_AST_SYSTEM_NAME ) ) {
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . system_name , " localhost " , sizeof ( cfg_paths . system_name ) ) ;
2007-05-11 21:15:30 +00:00
}
ast_log ( LOG_ERROR , " Cannot obtain hostname for this system. Using '%s' instead. \n " , ast_config_AST_SYSTEM_NAME ) ;
2007-05-11 19:56:57 +00:00
}
}
2006-05-30 21:37:11 +00:00
} else if ( ! strcasecmp ( v - > name , " languageprefix " ) ) {
ast_language_is_prefix = ast_true ( v - > value ) ;
2007-08-28 16:28:26 +00:00
} else if ( ! strcasecmp ( v - > name , " lockmode " ) ) {
if ( ! strcasecmp ( v - > value , " lockfile " ) ) {
ast_set_lock_type ( AST_LOCK_TYPE_LOCKFILE ) ;
} else if ( ! strcasecmp ( v - > value , " flock " ) ) {
ast_set_lock_type ( AST_LOCK_TYPE_FLOCK ) ;
} else {
ast_log ( LOG_WARNING , " '%s' is not a valid setting for the lockmode option, "
" defaulting to 'lockfile' \n " , v - > value ) ;
ast_set_lock_type ( AST_LOCK_TYPE_LOCKFILE ) ;
}
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
} else if ( ! strcasecmp ( v - > name , " minmemfree " ) ) {
/* specify the minimum amount of free memory to retain. Asterisk should stop accepting new calls
* if the amount of free memory falls below this watermark */
if ( ( sscanf ( v - > value , " %ld " , & option_minmemfree ) ! = 1 ) | | ( option_minmemfree < 0 ) ) {
option_minmemfree = 0 ;
}
2007-04-11 20:59:08 +00:00
# endif
2008-06-10 12:48:50 +00:00
} else if ( ! strcasecmp ( v - > name , " entityid " ) ) {
struct ast_eid tmp_eid ;
if ( ! ast_str_to_eid ( & tmp_eid , v - > value ) ) {
ast_verbose ( " Successfully set global EID to '%s' \n " , v - > value ) ;
g_eid = tmp_eid ;
} else
ast_verbose ( " Invalid Entity ID '%s' provided \n " , v - > value ) ;
2008-08-25 23:13:32 +00:00
} else if ( ! strcasecmp ( v - > name , " lightbackground " ) ) {
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_LIGHT_BACKGROUND ) ;
2008-10-07 17:44:32 +00:00
} else if ( ! strcasecmp ( v - > name , " forceblackbackground " ) ) {
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_FORCE_BLACK_BACKGROUND ) ;
2009-01-13 23:00:27 +00:00
} else if ( ! strcasecmp ( v - > name , " hideconnect " ) ) {
ast_set2_flag ( & ast_options , ast_true ( v - > value ) , AST_OPT_FLAG_HIDE_CONSOLE_CONNECT ) ;
2004-09-07 01:49:08 +00:00
}
}
2008-06-03 22:05:16 +00:00
for ( v = ast_variable_browse ( cfg , " compat " ) ; v ; v = v - > next ) {
float version ;
if ( sscanf ( v - > value , " %f " , & version ) ! = 1 ) {
ast_log ( LOG_WARNING , " Compatibility version for option '%s' is not a number: '%s' \n " , v - > name , v - > value ) ;
continue ;
}
if ( ! strcasecmp ( v - > name , " app_set " ) ) {
ast_set2_flag ( & ast_compat , version < 1.5 ? 1 : 0 , AST_COMPAT_APP_SET ) ;
} else if ( ! strcasecmp ( v - > name , " res_agi " ) ) {
ast_set2_flag ( & ast_compat , version < 1.5 ? 1 : 0 , AST_COMPAT_DELIM_RES_AGI ) ;
} else if ( ! strcasecmp ( v - > name , " pbx_realtime " ) ) {
ast_set2_flag ( & ast_compat , version < 1.5 ? 1 : 0 , AST_COMPAT_DELIM_PBX_REALTIME ) ;
}
}
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2003-02-06 06:15:25 +00:00
}
2007-02-23 23:25:22 +00:00
static void * monitor_sig_flags ( void * unused )
{
for ( ; ; ) {
struct pollfd p = { sig_alert_pipe [ 0 ] , POLLIN , 0 } ;
int a ;
poll ( & p , 1 , - 1 ) ;
if ( sig_flags . need_reload ) {
sig_flags . need_reload = 0 ;
ast_module_reload ( NULL ) ;
}
if ( sig_flags . need_quit ) {
sig_flags . need_quit = 0 ;
quit_handler ( 0 , 0 , 1 , 0 ) ;
}
2008-11-02 18:52:13 +00:00
if ( read ( sig_alert_pipe [ 0 ] , & a , sizeof ( a ) ) ! = sizeof ( a ) ) {
}
2007-02-23 23:25:22 +00:00
}
return NULL ;
}
2007-12-18 23:06:05 +00:00
static void * canary_thread ( void * unused )
{
struct stat canary_stat ;
2008-08-10 19:35:50 +00:00
struct timeval now ;
2007-12-18 23:06:05 +00:00
/* Give the canary time to sing */
sleep ( 120 ) ;
for ( ; ; ) {
stat ( canary_filename , & canary_stat ) ;
2008-08-10 19:35:50 +00:00
now = ast_tvnow ( ) ;
if ( now . tv_sec > canary_stat . st_mtime + 60 ) {
2008-01-17 00:05:13 +00:00
ast_log ( LOG_WARNING , " The canary is no more. He has ceased to be! He's expired and gone to meet his maker! He's a stiff! Bereft of life, he rests in peace. His metabolic processes are now history! He's off the twig! He's kicked the bucket. He's shuffled off his mortal coil, run down the curtain, and joined the bleeding choir invisible!! THIS is an EX-CANARY. (Reducing priority) \n " ) ;
2007-12-18 23:06:05 +00:00
ast_set_priority ( 0 ) ;
pthread_exit ( NULL ) ;
}
/* Check the canary once a minute */
sleep ( 60 ) ;
}
}
/* Used by libc's atexit(3) function */
static void canary_exit ( void )
{
if ( canary_pid > 0 )
kill ( canary_pid , SIGKILL ) ;
}
2008-01-17 00:05:13 +00:00
static void run_startup_commands ( void )
{
int fd ;
2008-01-22 20:33:16 +00:00
struct ast_config * cfg ;
struct ast_flags cfg_flags = { 0 } ;
struct ast_variable * v ;
2008-01-17 00:05:13 +00:00
2008-03-26 18:39:06 +00:00
if ( ! ( cfg = ast_config_load2 ( " cli.conf " , " " /* core, can't reload */ , cfg_flags ) ) )
2008-01-17 00:05:13 +00:00
return ;
2008-09-12 23:30:03 +00:00
if ( cfg = = CONFIG_STATUS_FILEMISSING | | cfg = = CONFIG_STATUS_FILEUNCHANGED | | cfg = = CONFIG_STATUS_FILEINVALID ) {
return ;
}
2008-01-17 00:05:13 +00:00
2008-01-22 20:33:16 +00:00
fd = open ( " /dev/null " , O_RDWR ) ;
2008-07-14 22:22:57 +00:00
if ( fd < 0 ) {
ast_config_destroy ( cfg ) ;
2008-01-22 20:33:16 +00:00
return ;
2008-07-14 22:22:57 +00:00
}
2008-01-17 00:05:13 +00:00
2008-01-22 20:41:05 +00:00
for ( v = ast_variable_browse ( cfg , " startup_commands " ) ; v ; v = v - > next ) {
if ( ast_true ( v - > value ) )
ast_cli_command ( fd , v - > name ) ;
}
2008-01-17 00:05:13 +00:00
close ( fd ) ;
2008-01-22 20:33:16 +00:00
ast_config_destroy ( cfg ) ;
2008-01-17 00:05:13 +00:00
}
1999-11-15 04:57:28 +00:00
int main ( int argc , char * argv [ ] )
{
2004-01-28 21:32:48 +00:00
int c ;
1999-12-19 22:38:55 +00:00
char filename [ 80 ] = " " ;
2006-03-31 00:33:28 +00:00
char hostname [ MAXHOSTNAMELEN ] = " " ;
2002-05-14 14:43:52 +00:00
char tmp [ 80 ] ;
2001-05-09 03:11:22 +00:00
char * xarg = NULL ;
2002-05-14 14:43:52 +00:00
int x ;
2002-09-12 03:22:07 +00:00
FILE * f ;
2001-05-09 03:11:22 +00:00
sigset_t sigs ;
2003-02-06 06:15:25 +00:00
int num ;
2007-10-17 15:39:24 +00:00
int isroot = 1 ;
2003-02-06 06:15:25 +00:00
char * buf ;
2007-12-18 10:24:58 +00:00
const char * runuser = NULL , * rungroup = NULL ;
2007-12-19 07:01:40 +00:00
char * remotesock = NULL ;
2001-05-09 03:11:22 +00:00
2002-05-14 14:43:52 +00:00
/* Remember original args for restart */
2008-07-11 18:09:35 +00:00
if ( argc > ARRAY_LEN ( _argv ) - 1 ) {
fprintf ( stderr , " Truncating argument size to %d \n " , ( int ) ARRAY_LEN ( _argv ) - 1 ) ;
argc = ARRAY_LEN ( _argv ) - 1 ;
2002-05-14 14:43:52 +00:00
}
2008-02-11 18:27:47 +00:00
for ( x = 0 ; x < argc ; x + + )
2002-05-14 14:43:52 +00:00
_argv [ x ] = argv [ x ] ;
_argv [ x ] = NULL ;
2007-10-17 15:39:24 +00:00
if ( geteuid ( ) ! = 0 )
isroot = 0 ;
2004-03-20 07:26:54 +00:00
/* if the progname is rasterisk consider it a remote console */
2004-10-01 18:35:35 +00:00
if ( argv [ 0 ] & & ( strstr ( argv [ 0 ] , " rasterisk " ) ) ! = NULL ) {
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE ) ;
2004-03-20 07:26:54 +00:00
}
2005-05-08 16:44:25 +00:00
if ( gethostname ( hostname , sizeof ( hostname ) - 1 ) )
2005-06-05 16:32:16 +00:00
ast_copy_string ( hostname , " <Unknown> " , sizeof ( hostname ) ) ;
2004-03-20 21:13:12 +00:00
ast_mainpid = getpid ( ) ;
2001-03-22 04:14:04 +00:00
ast_ulaw_init ( ) ;
2001-12-25 21:12:07 +00:00
ast_alaw_init ( ) ;
2001-03-22 04:14:04 +00:00
callerid_init ( ) ;
2006-03-28 22:25:08 +00:00
ast_builtins_init ( ) ;
2004-06-25 04:07:52 +00:00
ast_utils_init ( ) ;
2001-12-25 21:12:07 +00:00
tdd_init ( ) ;
2008-05-03 03:40:32 +00:00
ast_tps_init ( ) ;
2007-10-17 15:39:24 +00:00
1999-12-19 22:38:55 +00:00
if ( getenv ( " HOME " ) )
snprintf ( filename , sizeof ( filename ) , " %s/.asterisk_history " , getenv ( " HOME " ) ) ;
1999-11-15 04:57:28 +00:00
/* Check for options */
2008-10-07 17:44:32 +00:00
while ( ( c = getopt ( argc , argv , " mtThfFdvVqprRgciInx:U:G:C:L:M:e:s:WB " ) ) ! = - 1 ) {
2006-03-31 00:33:28 +00:00
switch ( c ) {
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
case ' e ' :
2007-04-11 22:10:26 +00:00
if ( ( sscanf ( & optarg [ 1 ] , " %ld " , & option_minmemfree ) ! = 1 ) | | ( option_minmemfree < 0 ) ) {
2007-04-11 19:11:32 +00:00
option_minmemfree = 0 ;
}
break ;
2007-04-11 20:59:08 +00:00
# endif
2006-08-21 20:12:18 +00:00
# if HAVE_WORKING_FORK
2006-04-30 14:55:05 +00:00
case ' F ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_ALWAYS_FORK ) ;
break ;
2006-08-21 20:12:18 +00:00
case ' f ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK ) ;
break ;
# endif
1999-11-15 04:57:28 +00:00
case ' d ' :
option_debug + + ;
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK ) ;
1999-12-19 22:38:55 +00:00
break ;
2000-01-02 20:59:00 +00:00
case ' c ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE ) ;
2001-03-22 04:14:04 +00:00
break ;
2002-05-14 14:43:52 +00:00
case ' n ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_COLOR ) ;
2002-05-14 14:43:52 +00:00
break ;
2001-05-09 03:11:22 +00:00
case ' r ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE ) ;
2001-05-09 03:11:22 +00:00
break ;
2004-06-25 14:39:38 +00:00
case ' R ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT ) ;
2004-06-25 14:39:38 +00:00
break ;
1999-12-19 22:38:55 +00:00
case ' p ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_HIGH_PRIORITY ) ;
1999-11-15 04:57:28 +00:00
break ;
case ' v ' :
option_verbose + + ;
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK ) ;
1999-11-15 04:57:28 +00:00
break ;
2006-05-26 19:48:17 +00:00
case ' m ' :
2006-05-26 21:47:52 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_MUTE ) ;
2006-05-26 19:48:17 +00:00
break ;
2005-05-18 01:49:13 +00:00
case ' M ' :
if ( ( sscanf ( optarg , " %d " , & option_maxcalls ) ! = 1 ) | | ( option_maxcalls < 0 ) )
option_maxcalls = 0 ;
break ;
2005-10-26 03:58:32 +00:00
case ' L ' :
if ( ( sscanf ( optarg , " %lf " , & option_maxload ) ! = 1 ) | | ( option_maxload < 0.0 ) )
option_maxload = 0.0 ;
break ;
1999-11-15 04:57:28 +00:00
case ' q ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_QUIET ) ;
1999-11-15 04:57:28 +00:00
break ;
2004-09-07 01:49:08 +00:00
case ' t ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_CACHE_RECORD_FILES ) ;
2004-09-07 01:49:08 +00:00
break ;
2005-03-11 07:24:10 +00:00
case ' T ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_TIMESTAMP ) ;
2005-03-11 07:24:10 +00:00
break ;
2001-05-09 03:11:22 +00:00
case ' x ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_EXEC ) ;
2008-01-08 19:06:27 +00:00
xarg = ast_strdupa ( optarg ) ;
2001-05-09 03:11:22 +00:00
break ;
2003-02-06 06:15:25 +00:00
case ' C ' :
2007-12-20 09:55:05 +00:00
ast_copy_string ( cfg_paths . config_file , optarg , sizeof ( cfg_paths . config_file ) ) ;
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_OVERRIDE_CONFIG ) ;
2003-02-06 06:15:25 +00:00
break ;
2006-03-30 06:07:04 +00:00
case ' I ' :
2006-03-30 06:26:16 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_INTERNAL_TIMING ) ;
2006-03-30 06:07:04 +00:00
break ;
2001-12-25 21:12:07 +00:00
case ' i ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_INIT_KEYS ) ;
2001-12-25 21:12:07 +00:00
break ;
2006-03-31 00:33:28 +00:00
case ' g ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_DUMP_CORE ) ;
2003-02-06 06:15:25 +00:00
break ;
2002-09-12 03:22:07 +00:00
case ' h ' :
show_cli_help ( ) ;
exit ( 0 ) ;
2004-07-18 17:58:05 +00:00
case ' V ' :
show_version ( ) ;
exit ( 0 ) ;
2004-07-18 16:20:54 +00:00
case ' U ' :
2008-01-08 19:06:27 +00:00
runuser = ast_strdupa ( optarg ) ;
2004-07-18 16:20:54 +00:00
break ;
case ' G ' :
2008-01-08 19:06:27 +00:00
rungroup = ast_strdupa ( optarg ) ;
2004-07-18 16:20:54 +00:00
break ;
2007-12-19 07:01:40 +00:00
case ' s ' :
2008-01-09 00:58:22 +00:00
remotesock = ast_strdupa ( optarg ) ;
2007-12-19 07:01:40 +00:00
break ;
2008-08-25 23:13:32 +00:00
case ' W ' : /* White background */
ast_set_flag ( & ast_options , AST_OPT_FLAG_LIGHT_BACKGROUND ) ;
2008-10-07 17:44:32 +00:00
ast_clear_flag ( & ast_options , AST_OPT_FLAG_FORCE_BLACK_BACKGROUND ) ;
break ;
case ' B ' : /* Force black background */
ast_set_flag ( & ast_options , AST_OPT_FLAG_FORCE_BLACK_BACKGROUND ) ;
ast_clear_flag ( & ast_options , AST_OPT_FLAG_LIGHT_BACKGROUND ) ;
2008-08-25 23:13:32 +00:00
break ;
1999-11-15 04:57:28 +00:00
case ' ? ' :
exit ( 1 ) ;
}
}
2002-05-14 14:43:52 +00:00
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
if ( ast_opt_console | | option_verbose | | ( ast_opt_remote & & ! ast_opt_exec ) ) {
2008-05-02 02:33:04 +00:00
if ( ast_register_verbose ( console_verboser ) ) {
ast_log ( LOG_WARNING , " Unable to register console verboser? \n " ) ;
}
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
WELCOME_MESSAGE ;
}
if ( ast_opt_console & & ! option_verbose )
ast_verbose ( " [ Booting... \n " ) ;
2005-09-29 02:38:24 +00:00
/* For remote connections, change the name of the remote connection.
* We do this for the benefit of init scripts ( which need to know if / when
* the main asterisk process has died yet ) . */
2005-12-04 20:40:46 +00:00
if ( ast_opt_remote ) {
2005-09-29 02:38:24 +00:00
strcpy ( argv [ 0 ] , " rasterisk " ) ;
for ( x = 1 ; x < argc ; x + + ) {
argv [ x ] = argv [ 0 ] + 10 ;
}
}
2008-11-12 17:38:20 +00:00
if ( ast_opt_console & & ! option_verbose ) {
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
ast_verbose ( " [ Reading Master Configuration ] \n " ) ;
2008-11-12 17:38:20 +00:00
}
2006-01-16 23:52:51 +00:00
ast_readconfig ( ) ;
2007-12-19 07:01:40 +00:00
if ( ast_opt_remote & & remotesock ! = NULL )
2007-12-27 23:28:01 +00:00
ast_copy_string ( ( char * ) cfg_paths . socket_path , remotesock , sizeof ( cfg_paths . socket_path ) ) ;
2007-12-19 07:01:40 +00:00
2006-12-27 21:18:27 +00:00
if ( ! ast_language_is_prefix & & ! ast_opt_remote )
ast_log ( LOG_WARNING , " 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 " ) ;
2008-11-12 17:38:20 +00:00
if ( ast_opt_always_fork & & ( ast_opt_remote | | ast_opt_console ) ) {
ast_log ( LOG_WARNING , " 'alwaysfork' is not compatible with console or remote console mode; ignored \n " ) ;
ast_clear_flag ( & ast_options , AST_OPT_FLAG_ALWAYS_FORK ) ;
}
2005-12-04 20:40:46 +00:00
if ( ast_opt_dump_core ) {
2003-02-06 06:15:25 +00:00
struct rlimit l ;
memset ( & l , 0 , sizeof ( l ) ) ;
l . rlim_cur = RLIM_INFINITY ;
l . rlim_max = RLIM_INFINITY ;
if ( setrlimit ( RLIMIT_CORE , & l ) ) {
ast_log ( LOG_WARNING , " Unable to disable core size resource limit: %s \n " , strerror ( errno ) ) ;
}
}
2005-11-08 00:30:29 +00:00
if ( ( ! rungroup ) & & ! ast_strlen_zero ( ast_config_AST_RUN_GROUP ) )
rungroup = ast_config_AST_RUN_GROUP ;
if ( ( ! runuser ) & & ! ast_strlen_zero ( ast_config_AST_RUN_USER ) )
runuser = ast_config_AST_RUN_USER ;
2006-03-31 00:33:28 +00:00
2007-12-18 23:06:05 +00:00
/* Must install this signal handler up here to ensure that if the canary
* fails to execute that it doesn ' t kill the Asterisk process .
*/
signal ( SIGCHLD , child_handler ) ;
2005-11-01 21:53:30 +00:00
# ifndef __CYGWIN__
2007-12-18 23:06:05 +00:00
if ( isroot ) {
2005-12-04 20:40:46 +00:00
ast_set_priority ( ast_opt_high_priority ) ;
2007-12-18 23:06:05 +00:00
if ( ast_opt_high_priority ) {
2009-02-24 20:06:48 +00:00
int cpipe [ 2 ] ;
/* PIPE signal ensures that astcanary dies when Asterisk dies */
2009-02-24 20:52:44 +00:00
if ( pipe ( cpipe ) ) {
fprintf ( stderr , " Unable to open pipe for canary process: %s \n " , strerror ( errno ) ) ;
exit ( 1 ) ;
}
2009-02-24 20:06:48 +00:00
canary_pipe = cpipe [ 0 ] ;
2007-12-18 23:06:05 +00:00
snprintf ( canary_filename , sizeof ( canary_filename ) , " %s/alt.asterisk.canary.tweet.tweet.tweet " , ast_config_AST_RUN_DIR ) ;
2009-02-24 20:06:48 +00:00
/* Don't let the canary child kill Asterisk, if it dies immediately */
signal ( SIGPIPE , SIG_IGN ) ;
2007-12-18 23:06:05 +00:00
canary_pid = fork ( ) ;
if ( canary_pid = = 0 ) {
char canary_binary [ 128 ] , * lastslash ;
int fd ;
/* Reset signal handler */
signal ( SIGCHLD , SIG_DFL ) ;
2009-02-24 20:06:48 +00:00
signal ( SIGPIPE , SIG_DFL ) ;
2007-12-18 23:06:05 +00:00
2009-02-24 20:06:48 +00:00
dup2 ( cpipe [ 1 ] , 100 ) ;
close ( cpipe [ 1 ] ) ;
for ( fd = 0 ; fd < 100 ; fd + + ) {
2007-12-18 23:06:05 +00:00
close ( fd ) ;
2009-02-24 20:06:48 +00:00
}
2007-12-18 23:06:05 +00:00
2008-01-03 01:59:27 +00:00
execlp ( " astcanary " , " astcanary " , canary_filename , ( char * ) NULL ) ;
2007-12-18 23:06:05 +00:00
/* If not found, try the same path as used to execute asterisk */
ast_copy_string ( canary_binary , argv [ 0 ] , sizeof ( canary_binary ) ) ;
if ( ( lastslash = strrchr ( canary_binary , ' / ' ) ) ) {
ast_copy_string ( lastslash + 1 , " astcanary " , sizeof ( canary_binary ) + canary_binary - ( lastslash + 1 ) ) ;
2008-01-03 01:59:27 +00:00
execl ( canary_binary , " astcanary " , canary_filename , ( char * ) NULL ) ;
2007-12-18 23:06:05 +00:00
}
/* Should never happen */
_exit ( 1 ) ;
} else if ( canary_pid > 0 ) {
pthread_t dont_care ;
2009-02-24 20:06:48 +00:00
close ( cpipe [ 1 ] ) ;
2007-12-18 23:06:05 +00:00
ast_pthread_create_detached ( & dont_care , NULL , canary_thread , NULL ) ;
}
/* Kill the canary when we exit */
atexit ( canary_exit ) ;
}
}
2005-03-26 07:16:18 +00:00
2007-10-17 15:39:24 +00:00
if ( isroot & & rungroup ) {
2004-07-18 16:20:54 +00:00
struct group * gr ;
gr = getgrnam ( rungroup ) ;
if ( ! gr ) {
ast_log ( LOG_WARNING , " No such group '%s'! \n " , rungroup ) ;
exit ( 1 ) ;
}
2004-07-18 18:52:36 +00:00
if ( setgid ( gr - > gr_gid ) ) {
2006-03-02 22:27:50 +00:00
ast_log ( LOG_WARNING , " Unable to setgid to %d (%s) \n " , ( int ) gr - > gr_gid , rungroup ) ;
2004-07-18 16:20:54 +00:00
exit ( 1 ) ;
}
2005-11-08 00:30:29 +00:00
if ( setgroups ( 0 , NULL ) ) {
ast_log ( LOG_WARNING , " Unable to drop unneeded groups \n " ) ;
exit ( 1 ) ;
}
2004-07-18 16:20:54 +00:00
if ( option_verbose )
ast_verbose ( " Running as group '%s' \n " , rungroup ) ;
}
2007-10-17 15:39:24 +00:00
if ( runuser & & ! ast_test_flag ( & ast_options , AST_OPT_FLAG_REMOTE ) ) {
2006-09-27 21:48:01 +00:00
# ifdef HAVE_CAP
int has_cap = 1 ;
# endif /* HAVE_CAP */
2004-07-18 16:20:54 +00:00
struct passwd * pw ;
pw = getpwnam ( runuser ) ;
if ( ! pw ) {
ast_log ( LOG_WARNING , " No such user '%s'! \n " , runuser ) ;
exit ( 1 ) ;
}
2006-09-27 21:48:01 +00:00
# ifdef HAVE_CAP
if ( prctl ( PR_SET_KEEPCAPS , 1 , 0 , 0 , 0 ) ) {
ast_log ( LOG_WARNING , " Unable to keep capabilities. \n " ) ;
2006-10-02 16:00:11 +00:00
has_cap = 0 ;
2006-09-27 21:48:01 +00:00
}
# endif /* HAVE_CAP */
2007-10-17 15:39:24 +00:00
if ( ! isroot & & pw - > pw_uid ! = geteuid ( ) ) {
ast_log ( LOG_ERROR , " Asterisk started as nonroot, but runuser '%s' requested. \n " , runuser ) ;
exit ( 1 ) ;
}
2006-01-08 20:27:22 +00:00
if ( ! rungroup ) {
if ( setgid ( pw - > pw_gid ) ) {
2006-03-02 22:27:50 +00:00
ast_log ( LOG_WARNING , " Unable to setgid to %d! \n " , ( int ) pw - > pw_gid ) ;
2006-01-08 20:27:22 +00:00
exit ( 1 ) ;
}
2007-12-21 15:14:52 +00:00
if ( isroot & & initgroups ( pw - > pw_name , pw - > pw_gid ) ) {
2006-01-07 20:08:51 +00:00
ast_log ( LOG_WARNING , " Unable to init groups for '%s' \n " , runuser ) ;
exit ( 1 ) ;
}
2006-01-07 19:42:05 +00:00
}
2004-07-18 16:20:54 +00:00
if ( setuid ( pw - > pw_uid ) ) {
2006-03-02 22:27:50 +00:00
ast_log ( LOG_WARNING , " Unable to setuid to %d (%s) \n " , ( int ) pw - > pw_uid , runuser ) ;
2004-07-18 16:20:54 +00:00
exit ( 1 ) ;
}
if ( option_verbose )
ast_verbose ( " Running as user '%s' \n " , runuser ) ;
2006-09-27 21:48:01 +00:00
# ifdef HAVE_CAP
if ( has_cap ) {
2006-10-02 16:00:11 +00:00
cap_t cap ;
2009-01-29 23:15:40 +00:00
cap = cap_from_text ( " cap_net_admin=eip " ) ;
2006-10-02 16:00:11 +00:00
if ( cap_set_proc ( cap ) )
2006-09-27 21:48:01 +00:00
ast_log ( LOG_WARNING , " Unable to install capabilities. \n " ) ;
2006-10-02 16:00:11 +00:00
if ( cap_free ( cap ) )
2006-09-27 21:48:01 +00:00
ast_log ( LOG_WARNING , " Unable to drop capabilities. \n " ) ;
}
# endif /* HAVE_CAP */
2004-07-18 16:20:54 +00:00
}
2005-11-01 21:53:30 +00:00
# endif /* __CYGWIN__ */
2006-02-14 18:47:16 +00:00
# ifdef linux
2006-02-14 02:41:42 +00:00
if ( geteuid ( ) & & ast_opt_dump_core ) {
if ( prctl ( PR_SET_DUMPABLE , 1 , 0 , 0 , 0 ) < 0 ) {
ast_log ( LOG_WARNING , " Unable to set the process for core dumps after changing to a non-root user. %s \n " , strerror ( errno ) ) ;
}
}
2006-02-14 18:47:16 +00:00
# endif
2006-02-14 02:41:42 +00:00
2006-10-04 00:26:21 +00:00
ast_term_init ( ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_end ( ) ) ;
2002-05-14 14:43:52 +00:00
fflush ( stdout ) ;
2004-06-22 17:42:14 +00:00
2005-12-04 20:40:46 +00:00
if ( ast_opt_console & & ! option_verbose )
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
ast_verbose ( " [ Initializing Custom Configuration Options ] \n " ) ;
2004-06-11 00:12:35 +00:00
/* custom config setup */
register_config_cli ( ) ;
2005-01-25 06:10:20 +00:00
read_config_maps ( ) ;
2004-06-11 00:12:35 +00:00
2005-12-04 20:40:46 +00:00
if ( ast_opt_console ) {
2004-06-29 04:42:19 +00:00
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
2003-02-06 06:15:25 +00:00
2004-06-29 04:42:19 +00:00
if ( ! ast_strlen_zero ( filename ) )
ast_el_read_history ( filename ) ;
2003-04-16 13:43:11 +00:00
}
2003-02-06 06:15:25 +00:00
2001-05-09 03:11:22 +00:00
if ( ast_tryconnect ( ) ) {
/* One is already running */
2005-12-04 20:40:46 +00:00
if ( ast_opt_remote ) {
if ( ast_opt_exec ) {
2001-05-09 03:11:22 +00:00
ast_remotecontrol ( xarg ) ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 0 , 0 , 0 ) ;
2001-05-09 03:11:22 +00:00
exit ( 0 ) ;
}
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
ast_remotecontrol ( NULL ) ;
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 0 , 0 , 0 ) ;
2001-05-09 03:11:22 +00:00
exit ( 0 ) ;
} else {
2005-12-04 20:40:46 +00:00
ast_log ( LOG_ERROR , " Asterisk already running on %s. Use 'asterisk -r' to connect. \n " , ast_config_AST_SOCKET ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
exit ( 1 ) ;
}
2005-12-04 20:40:46 +00:00
} else if ( ast_opt_remote | | ast_opt_exec ) {
2006-03-31 00:33:28 +00:00
ast_log ( LOG_ERROR , " Unable to connect to remote asterisk (does %s exist?) \n " , ast_config_AST_SOCKET ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
exit ( 1 ) ;
}
2002-09-12 03:22:07 +00:00
/* Blindly write pid file since we couldn't connect */
2005-12-04 20:40:46 +00:00
unlink ( ast_config_AST_PID ) ;
f = fopen ( ast_config_AST_PID , " w " ) ;
2002-09-12 03:22:07 +00:00
if ( f ) {
2006-05-08 12:32:44 +00:00
fprintf ( f , " %ld \n " , ( long ) getpid ( ) ) ;
2002-09-12 03:22:07 +00:00
fclose ( f ) ;
} else
2005-12-04 20:40:46 +00:00
ast_log ( LOG_WARNING , " Unable to open pid file '%s': %s \n " , ast_config_AST_PID , strerror ( errno ) ) ;
2001-12-25 21:12:07 +00:00
2006-08-21 20:12:18 +00:00
# if HAVE_WORKING_FORK
2006-04-30 14:55:05 +00:00
if ( ast_opt_always_fork | | ! ast_opt_no_fork ) {
2008-02-04 21:15:18 +00:00
# ifndef HAVE_SBIN_LAUNCHD
2008-11-02 18:52:13 +00:00
if ( daemon ( 1 , 0 ) < 0 ) {
ast_log ( LOG_ERROR , " daemon() failed: %s \n " , strerror ( errno ) ) ;
}
2006-05-08 12:32:44 +00:00
ast_mainpid = getpid ( ) ;
2003-10-16 10:27:41 +00:00
/* Blindly re-write pid file since we are forking */
2005-12-04 20:40:46 +00:00
unlink ( ast_config_AST_PID ) ;
f = fopen ( ast_config_AST_PID , " w " ) ;
2003-10-16 10:27:41 +00:00
if ( f ) {
2006-05-08 12:32:44 +00:00
fprintf ( f , " %ld \n " , ( long ) ast_mainpid ) ;
2003-10-16 10:27:41 +00:00
fclose ( f ) ;
} else
2005-12-04 20:40:46 +00:00
ast_log ( LOG_WARNING , " Unable to open pid file '%s': %s \n " , ast_config_AST_PID , strerror ( errno ) ) ;
2008-02-04 21:15:18 +00:00
# else
ast_log ( LOG_WARNING , " Mac OS X detected. Use '/sbin/launchd -d' to launch with the nofork option. \n " ) ;
# endif
2001-05-09 03:11:22 +00:00
}
2006-08-21 20:12:18 +00:00
# endif
2001-12-25 21:12:07 +00:00
2007-09-20 16:27:07 +00:00
ast_event_init ( ) ;
2001-05-09 03:11:22 +00:00
ast_makesocket ( ) ;
sigemptyset ( & sigs ) ;
sigaddset ( & sigs , SIGHUP ) ;
sigaddset ( & sigs , SIGTERM ) ;
sigaddset ( & sigs , SIGINT ) ;
sigaddset ( & sigs , SIGPIPE ) ;
sigaddset ( & sigs , SIGWINCH ) ;
pthread_sigmask ( SIG_BLOCK , & sigs , NULL ) ;
1999-11-15 04:57:28 +00:00
signal ( SIGURG , urg_handler ) ;
2002-05-14 14:43:52 +00:00
signal ( SIGINT , __quit_handler ) ;
signal ( SIGTERM , __quit_handler ) ;
2001-05-09 03:11:22 +00:00
signal ( SIGHUP , hup_handler ) ;
2003-09-16 19:35:57 +00:00
signal ( SIGPIPE , SIG_IGN ) ;
2005-04-13 04:47:39 +00:00
/* ensure that the random number generators are seeded with a different value every time
Asterisk is started
*/
srand ( ( unsigned int ) getpid ( ) + ( unsigned int ) time ( NULL ) ) ;
2006-01-10 00:55:45 +00:00
initstate ( ( unsigned int ) getpid ( ) * 65536 + ( unsigned int ) time ( NULL ) , randompool , sizeof ( randompool ) ) ;
2005-04-13 04:47:39 +00:00
2006-10-29 20:47:01 +00:00
if ( init_logger ( ) ) { /* Start logging subsystem */
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
1999-11-15 04:57:28 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
2008-06-13 12:45:50 +00:00
2007-01-04 23:18:36 +00:00
threadstorage_init ( ) ;
2007-09-13 18:52:35 +00:00
astobj2_init ( ) ;
3) In addition to merging the changes below, change trunk back to a regular
LIST instead of an RWLIST. The way this list works makes it such that
a RWLIST provides no additional benefit. Also, a mutex is needed for
use with the thread condition.
Merged revisions 105563 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r105563 | russell | 2008-03-03 09:50:43 -0600 (Mon, 03 Mar 2008) | 24 lines
Merge in some changes from team/russell/autoservice-nochans-1.4
These changes fix up some dubious code that I came across while auditing what
happens in the autoservice thread when there are no channels currently in
autoservice.
1) Change it so that autoservice thread doesn't keep looping around calling
ast_waitfor_n() on 0 channels twice a second. Instead, use a thread condition
so that the thread properly goes to sleep and does not wake up until a
channel is put into autoservice.
This actually fixes an interesting bug, as well. If the autoservice thread
is already running (almost always is the case), then when the thread goes
from having 0 channels to have 1 channel to autoservice, that channel would
have to wait for up to 1/2 of a second to have the first frame read from it.
2) Fix up the code in ast_waitfor_nandfds() for when it gets called with no
channels and no fds to poll() on, such as was the case with the previous code
for the autoservice thread. In this case, the code would call alloca(0), and
pass the result as the first argument to poll(). In this case, the 2nd
argument to poll() specified that there were no fds, so this invalid pointer
shouldn't actually get dereferenced, but, this code makes it explicit and
ensures the pointers are NULL unless we have valid data to put there.
(related to issue #12116)
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@105564 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-03-03 15:59:50 +00:00
ast_autoservice_init ( ) ;
2008-06-16 13:03:40 +00:00
if ( ast_timing_init ( ) ) {
printf ( " %s " , term_quit ( ) ) ;
exit ( 1 ) ;
}
2008-11-01 21:10:07 +00:00
# ifdef AST_XML_DOCS
/* Load XML documentation. */
2008-11-10 13:53:23 +00:00
ast_xmldoc_load_documentation ( ) ;
2008-11-01 21:10:07 +00:00
# endif
Merge major changes to the way device state is passed around Asterisk. The two
places that cared about device states were app_queue and the hint code in pbx.c.
The changes include converting it to use the Asterisk event system, as well as
other efficiency improvements.
* app_queue: This module used to register a callback into devicestate.c to
monitor device state changes. Now, it is just a subscriber to Asterisk
events with the type, device state.
* pbx.c hints: Previously, the device state processing thread in devicestate.c
would call ast_hint_state_changed() each time the state of a device changed.
Then, that code would go looking for all the hints that monitor that device,
and call their callbacks. All of this blocked the device state processing
thread. Now, the hint code is a subscriber of Asterisk events with the
type, device state. Furthermore, when this code receives a device state
change event, it queues it up to be processed by another thread so that it
doesn't block one of the event processing threads.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@66958 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-01 23:34:43 +00:00
if ( load_modules ( 1 ) ) { /* Load modules, pre-load only */
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2005-08-14 23:47:40 +00:00
exit ( 1 ) ;
}
2006-08-21 02:11:39 +00:00
2006-10-29 20:47:01 +00:00
if ( dnsmgr_init ( ) ) { /* Initialize the DNS manager */
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2005-07-05 22:11:43 +00:00
exit ( 1 ) ;
}
2006-08-21 02:11:39 +00:00
2006-10-29 20:47:01 +00:00
ast_http_init ( ) ; /* Start the HTTP server, if needed */
2006-08-21 02:11:39 +00:00
2004-12-31 00:04:41 +00:00
ast_channels_init ( ) ;
2006-08-21 02:11:39 +00:00
2005-06-03 01:42:31 +00:00
if ( ast_cdr_engine_init ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2005-06-03 01:42:31 +00:00
exit ( 1 ) ;
}
2006-08-21 02:11:39 +00:00
2005-07-08 21:14:34 +00:00
if ( ast_device_state_engine_init ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2005-07-08 21:14:34 +00:00
exit ( 1 ) ;
}
2006-08-21 02:11:39 +00:00
2003-05-16 02:50:46 +00:00
ast_rtp_init ( ) ;
2008-03-05 16:23:44 +00:00
ast_dsp_init ( ) ;
2006-01-12 17:14:58 +00:00
ast_udptl_init ( ) ;
2006-08-21 02:11:39 +00:00
2002-05-14 14:43:52 +00:00
if ( ast_image_init ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-10-11 18:51:39 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
2006-08-21 02:11:39 +00:00
2004-06-30 03:22:29 +00:00
if ( ast_file_init ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2004-06-30 03:22:29 +00:00
exit ( 1 ) ;
}
2006-08-21 02:11:39 +00:00
2002-05-14 14:43:52 +00:00
if ( load_pbx ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
1999-11-15 04:57:28 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
2006-08-21 02:11:39 +00:00
2009-02-17 20:41:24 +00:00
if ( ast_indications_init ( ) ) {
printf ( " %s " , term_quit ( ) ) ;
exit ( 1 ) ;
}
2008-01-23 23:09:11 +00:00
ast_features_init ( ) ;
2002-05-14 14:43:52 +00:00
if ( init_framer ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-10-11 18:51:39 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
2006-08-21 02:11:39 +00:00
2003-02-06 06:15:25 +00:00
if ( astdb_init ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2003-02-06 06:15:25 +00:00
exit ( 1 ) ;
}
2006-08-21 02:11:39 +00:00
2003-05-01 04:29:25 +00:00
if ( ast_enum_init ( ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2003-05-01 04:29:25 +00:00
exit ( 1 ) ;
}
2005-11-08 01:29:14 +00:00
2006-08-21 22:23:26 +00:00
if ( load_modules ( 0 ) ) {
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2006-08-21 22:23:26 +00:00
exit ( 1 ) ;
}
2008-12-01 18:52:14 +00:00
/* loads the cli_permissoins.conf file needed to implement cli restrictions. */
ast_cli_perms_init ( 0 ) ;
2008-10-25 11:02:11 +00:00
/* AMI is initialized after loading modules because of a potential
* conflict between issuing a module reload from manager and
* registering manager actions . This will cause reversed locking
* order between the module list and manager actions list . */
if ( init_manager ( ) ) {
printf ( " %s " , term_quit ( ) ) ;
exit ( 1 ) ;
}
2005-11-08 01:29:14 +00:00
dnsmgr_start_refresh ( ) ;
1999-11-15 04:57:28 +00:00
/* We might have the option of showing a console, but for now just
do nothing . . . */
2005-12-04 20:40:46 +00:00
if ( ast_opt_console & & ! option_verbose )
2000-01-02 20:59:00 +00:00
ast_verbose ( " ] \n " ) ;
2005-12-04 20:40:46 +00:00
if ( option_verbose | | ast_opt_console )
2008-03-18 15:43:34 +00:00
ast_verbose ( " %s " , term_color ( tmp , " Asterisk Ready. \n " , COLOR_BRWHITE , COLOR_BLACK , sizeof ( tmp ) ) ) ;
2005-12-04 20:40:46 +00:00
if ( ast_opt_no_fork )
2004-03-02 23:50:03 +00:00
consolethread = pthread_self ( ) ;
2006-08-21 02:11:39 +00:00
2007-02-23 23:25:22 +00:00
if ( pipe ( sig_alert_pipe ) )
sig_alert_pipe [ 0 ] = sig_alert_pipe [ 1 ] = - 1 ;
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_FULLY_BOOTED ) ;
2001-05-09 03:11:22 +00:00
pthread_sigmask ( SIG_UNBLOCK , & sigs , NULL ) ;
2006-08-21 02:11:39 +00:00
2003-04-28 19:58:43 +00:00
# ifdef __AST_DEBUG_MALLOC
__ast_mm_init ( ) ;
# endif
2006-08-21 02:11:39 +00:00
2007-11-27 21:10:50 +00:00
ast_lastreloadtime = ast_startuptime = ast_tvnow ( ) ;
2008-12-05 10:31:25 +00:00
ast_cli_register_multiple ( cli_asterisk , ARRAY_LEN ( cli_asterisk ) ) ;
2006-08-21 02:11:39 +00:00
2008-01-17 00:05:13 +00:00
run_startup_commands ( ) ;
2005-12-04 20:40:46 +00:00
if ( ast_opt_console ) {
2000-01-02 20:59:00 +00:00
/* Console stuff now... */
/* Register our quit function */
2000-10-25 23:22:50 +00:00
char title [ 256 ] ;
2007-02-23 23:25:22 +00:00
pthread_t dont_care ;
2007-05-24 18:30:19 +00:00
ast_pthread_create_detached ( & dont_care , NULL , monitor_sig_flags , NULL ) ;
2007-02-23 23:25:22 +00:00
2000-10-25 23:22:50 +00:00
set_icon ( " Asterisk " ) ;
2006-05-08 12:32:44 +00:00
snprintf ( title , sizeof ( title ) , " Asterisk Console on '%s' (pid %ld) " , hostname , ( long ) ast_mainpid ) ;
2000-10-25 23:22:50 +00:00
set_title ( title ) ;
2003-02-06 06:15:25 +00:00
2003-05-22 14:24:06 +00:00
for ( ; ; ) {
2007-09-20 19:42:33 +00:00
buf = ( char * ) el_gets ( el , & num ) ;
2007-06-27 20:47:45 +00:00
2007-06-27 23:30:31 +00:00
if ( ! buf & & write ( 1 , " " , 1 ) < 0 )
goto lostterm ;
2007-06-24 20:07:15 +00:00
if ( buf ) {
if ( buf [ strlen ( buf ) - 1 ] = = ' \n ' )
buf [ strlen ( buf ) - 1 ] = ' \0 ' ;
2003-05-22 14:24:06 +00:00
2007-06-24 20:07:15 +00:00
consolehandler ( ( char * ) buf ) ;
} else if ( ast_opt_remote & & ( write ( STDOUT_FILENO , " \n Use EXIT or QUIT to exit the asterisk console \n " ,
2006-09-26 21:01:02 +00:00
strlen ( " \n Use EXIT or QUIT to exit the asterisk console \n " ) ) < 0 ) ) {
/* Whoa, stdout disappeared from under us... Make /dev/null's */
int fd ;
fd = open ( " /dev/null " , O_RDWR ) ;
if ( fd > - 1 ) {
dup2 ( fd , STDOUT_FILENO ) ;
dup2 ( fd , STDIN_FILENO ) ;
} else
ast_log ( LOG_WARNING , " Failed to open /dev/null to recover from dead console. Bad things will happen! \n " ) ;
break ;
2003-08-21 02:34:03 +00:00
}
2003-02-06 06:15:25 +00:00
}
2000-01-02 20:59:00 +00:00
}
2007-02-23 23:25:22 +00:00
monitor_sig_flags ( NULL ) ;
2006-08-21 20:12:18 +00:00
2007-06-27 23:30:31 +00:00
lostterm :
1999-11-15 04:57:28 +00:00
return 0 ;
}