1999-11-15 04:57:28 +00:00
/*
* Asterisk - - A telephony toolkit for Linux .
*
* Top level source file for asterisk
*
1999-12-19 22:38:55 +00:00
* Copyright ( C ) 1999 , Mark Spencer
1999-11-15 04:57:28 +00:00
*
* Mark Spencer < markster @ linux - support . net >
*
* This program is free software , distributed under the terms of
* the GNU General Public License
*/
# include <unistd.h>
# include <stdlib.h>
# include <asterisk/logger.h>
# include <asterisk/options.h>
1999-12-19 22:38:55 +00:00
# include <asterisk/cli.h>
2000-01-09 19:58:18 +00:00
# include <asterisk/channel.h>
2001-03-22 04:14:04 +00:00
# include <asterisk/ulaw.h>
2001-12-25 21:12:07 +00:00
# include <asterisk/alaw.h>
2001-03-22 04:14:04 +00:00
# include <asterisk/callerid.h>
2001-05-09 03:11:22 +00:00
# include <asterisk/module.h>
2001-10-11 18:51:39 +00:00
# include <asterisk/image.h>
2001-12-25 21:12:07 +00:00
# include <asterisk/tdd.h>
2002-05-14 14:43:52 +00:00
# include <asterisk/term.h>
2002-09-12 03:22:07 +00:00
# include <asterisk/manager.h>
2003-02-06 06:15:25 +00:00
# include <asterisk/pbx.h>
2003-05-01 04:29:25 +00:00
# include <asterisk/enum.h>
2003-05-16 02:50:46 +00:00
# include <asterisk/rtp.h>
2003-02-06 06:15:25 +00:00
# include <sys/resource.h>
2001-10-11 18:51:39 +00:00
# include <fcntl.h>
1999-11-15 04:57:28 +00:00
# include <stdio.h>
# include <signal.h>
1999-12-19 22:38:55 +00:00
# include <sched.h>
2001-12-25 21:12:07 +00:00
# include <asterisk/io.h>
1999-12-19 22:38:55 +00:00
# include <pthread.h>
2001-05-09 03:11:22 +00:00
# include <sys/socket.h>
# include <sys/un.h>
# include <sys/select.h>
# include <string.h>
# include <errno.h>
2003-02-06 06:15:25 +00:00
# include <ctype.h>
# include "editline/histedit.h"
1999-11-15 04:57:28 +00:00
# include "asterisk.h"
2003-02-06 06:15:25 +00:00
# include <asterisk/config.h>
1999-11-15 04:57:28 +00:00
2001-05-09 03:11:22 +00:00
# define AST_MAX_CONNECTS 128
# define NUM_MSGS 64
1999-11-15 04:57:28 +00:00
int option_verbose = 0 ;
int option_debug = 0 ;
int option_nofork = 0 ;
int option_quiet = 0 ;
2000-01-02 20:59:00 +00:00
int option_console = 0 ;
1999-12-19 22:38:55 +00:00
int option_highpriority = 0 ;
2001-05-09 03:11:22 +00:00
int option_remote = 0 ;
int option_exec = 0 ;
2001-12-25 21:12:07 +00:00
int option_initcrypto = 0 ;
2002-05-14 14:43:52 +00:00
int option_nocolor ;
2003-02-06 06:15:25 +00:00
int option_dumpcore = 0 ;
int option_overrideconfig = 0 ;
2000-01-02 20:59:00 +00:00
int fully_booted = 0 ;
1999-12-19 22:38:55 +00:00
2001-05-09 03:11:22 +00:00
static int ast_socket = - 1 ; /* UNIX Socket for allowing remote control */
static int ast_consock = - 1 ; /* UNIX Socket for controlling another asterisk */
static int mainpid ;
struct console {
int fd ; /* File descriptor */
int p [ 2 ] ; /* Pipe */
pthread_t t ; /* Thread of handler */
} ;
2003-05-02 15:37:34 +00:00
time_t ast_startuptime ;
time_t ast_lastreloadtime ;
2003-02-06 06:15:25 +00:00
static History * el_hist = NULL ;
static EditLine * el = NULL ;
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 * ) ;
char ast_config_AST_CONFIG_DIR [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_CONFIG_FILE [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_MODULE_DIR [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_SPOOL_DIR [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_VAR_DIR [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_LOG_DIR [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_AGI_DIR [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_DB [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_KEY_DIR [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_PID [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_SOCKET [ AST_CONFIG_MAX_PATH ] ;
char ast_config_AST_RUN_DIR [ AST_CONFIG_MAX_PATH ] ;
2003-03-16 22:37:31 +00:00
static int fdprint ( int fd , const char * s )
2001-05-09 03:11:22 +00:00
{
return write ( fd , s , strlen ( s ) + 1 ) ;
}
2003-03-16 22:37:31 +00:00
static void network_verboser ( const char * s , int pos , int replace , int complete )
2001-05-09 03:11:22 +00:00
{
int x ;
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
if ( consoles [ x ] . fd > - 1 )
fdprint ( consoles [ x ] . p [ 1 ] , s ) ;
}
}
static pthread_t lthread ;
static void * netconsole ( void * vconsole )
{
struct console * con = vconsole ;
char hostname [ 256 ] ;
char tmp [ 512 ] ;
int res ;
int max ;
fd_set rfds ;
if ( gethostname ( hostname , sizeof ( hostname ) ) )
2001-12-25 21:12:07 +00:00
strncpy ( hostname , " <Unknown> " , sizeof ( hostname ) - 1 ) ;
2001-05-09 03:11:22 +00:00
snprintf ( tmp , sizeof ( tmp ) , " %s/%d/%s \n " , hostname , mainpid , ASTERISK_VERSION ) ;
fdprint ( con - > fd , tmp ) ;
for ( ; ; ) {
FD_ZERO ( & rfds ) ;
FD_SET ( con - > fd , & rfds ) ;
FD_SET ( con - > p [ 0 ] , & rfds ) ;
max = con - > fd ;
if ( con - > p [ 0 ] > max )
max = con - > p [ 0 ] ;
2003-04-27 18:13:11 +00:00
res = ast_select ( max + 1 , & rfds , NULL , NULL , NULL ) ;
2001-05-09 03:11:22 +00:00
if ( res < 0 ) {
ast_log ( LOG_WARNING , " select returned < 0: %s \n " , strerror ( errno ) ) ;
continue ;
}
if ( FD_ISSET ( con - > fd , & rfds ) ) {
res = read ( con - > fd , tmp , sizeof ( tmp ) ) ;
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 ;
ast_cli_command ( con - > fd , tmp ) ;
}
if ( FD_ISSET ( con - > p [ 0 ] , & rfds ) ) {
res = read ( con - > p [ 0 ] , tmp , sizeof ( tmp ) ) ;
if ( res < 1 ) {
ast_log ( LOG_ERROR , " read returned %d \n " , res ) ;
break ;
}
res = write ( con - > fd , tmp , res ) ;
if ( res < 1 )
break ;
}
}
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Remote UNIX connection disconnected \n " ) ;
close ( con - > fd ) ;
close ( con - > p [ 0 ] ) ;
close ( con - > p [ 1 ] ) ;
con - > fd = - 1 ;
return NULL ;
}
static void * listener ( void * unused )
{
struct sockaddr_un sun ;
int s ;
int len ;
int x ;
2001-10-11 18:51:39 +00:00
int flags ;
2001-05-09 03:11:22 +00:00
pthread_attr_t attr ;
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_DETACHED ) ;
for ( ; ; ) {
2002-09-12 03:22:07 +00:00
if ( ast_socket < 0 )
return NULL ;
2001-05-09 03:11:22 +00:00
len = sizeof ( sun ) ;
s = accept ( ast_socket , ( struct sockaddr * ) & sun , & len ) ;
if ( s < 0 ) {
ast_log ( LOG_WARNING , " Accept retured %d: %s \n " , s , strerror ( errno ) ) ;
} else {
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
if ( consoles [ x ] . fd < 0 ) {
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 ;
if ( pthread_create ( & consoles [ x ] . t , & attr , netconsole , & consoles [ x ] ) ) {
ast_log ( LOG_ERROR , " Unable to spawn thread to handle connection \n " ) ;
consoles [ x ] . fd = - 1 ;
fdprint ( s , " Server failed to spawn thread \n " ) ;
close ( s ) ;
}
break ;
}
}
if ( x > = AST_MAX_CONNECTS ) {
fdprint ( s , " No more connections allowed \n " ) ;
ast_log ( LOG_WARNING , " No more connections allowed \n " ) ;
close ( s ) ;
} else if ( consoles [ x ] . fd > - 1 ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Remote UNIX connection \n " ) ;
}
}
}
return NULL ;
}
static int ast_makesocket ( void )
{
struct sockaddr_un sun ;
int res ;
int x ;
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + )
consoles [ x ] . fd = - 1 ;
2003-02-06 06:15:25 +00:00
unlink ( ( char * ) 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 ;
}
memset ( & sun , 0 , sizeof ( sun ) ) ;
sun . sun_family = AF_LOCAL ;
2003-02-06 06:15:25 +00:00
strncpy ( sun . sun_path , ( char * ) ast_config_AST_SOCKET , sizeof ( sun . sun_path ) - 1 ) ;
2001-05-09 03:11:22 +00:00
res = bind ( ast_socket , ( struct sockaddr * ) & sun , sizeof ( sun ) ) ;
if ( res ) {
2003-02-06 06:15:25 +00:00
ast_log ( LOG_WARNING , " Unable to bind socket to %s: %s \n " , ( char * ) 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 ) {
2003-02-06 06:15:25 +00:00
ast_log ( LOG_WARNING , " Unable to listen on socket %s: %s \n " , ( char * ) ast_config_AST_SOCKET , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
ast_socket = - 1 ;
return - 1 ;
}
ast_register_verbose ( network_verboser ) ;
pthread_create ( & lthread , NULL , listener , NULL ) ;
return 0 ;
}
static int ast_tryconnect ( void )
{
struct sockaddr_un sun ;
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 ;
}
memset ( & sun , 0 , sizeof ( sun ) ) ;
sun . sun_family = AF_LOCAL ;
2003-02-06 06:15:25 +00:00
strncpy ( sun . sun_path , ( char * ) ast_config_AST_SOCKET , sizeof ( sun . sun_path ) - 1 ) ;
2001-05-09 03:11:22 +00:00
res = connect ( ast_consock , ( struct sockaddr * ) & sun , sizeof ( sun ) ) ;
if ( res ) {
close ( ast_consock ) ;
ast_consock = - 1 ;
return 0 ;
} else
return 1 ;
}
1999-11-15 04:57:28 +00:00
static void urg_handler ( int num )
{
/* Called by soft_hangup to interrupt the select, read, or other
system call . We don ' t actually need to do anything though . */
2001-05-09 03:11:22 +00:00
if ( option_debug )
1999-11-15 04:57:28 +00:00
ast_log ( LOG_DEBUG , " Urgent handler \n " ) ;
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 )
{
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Received HUP signal -- Reloading configs \n " ) ;
ast_module_reload ( ) ;
}
static void pipe_handler ( int num )
{
/* Ignore sigpipe */
}
2000-10-25 23:22:50 +00:00
static void set_title ( char * text )
{
/* Set an X-term or screen title */
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 ) ;
}
1999-12-19 22:38:55 +00:00
static int set_priority ( int pri )
{
struct sched_param sched ;
2001-03-22 04:14:04 +00:00
memset ( & sched , 0 , sizeof ( sched ) ) ;
1999-12-19 22:38:55 +00:00
/* We set ourselves to a high priority, that we might pre-empt everything
else . If your PBX has heavy activity on it , this is a good thing . */
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 ;
if ( sched_setscheduler ( 0 , SCHED_OTHER , & sched ) ) {
ast_log ( LOG_WARNING , " Unable to set normal priority \n " ) ;
return - 1 ;
}
}
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 {
if ( setpriority ( PRIO_PROCESS , 0 , 0 ) = = - 1 ) {
ast_log ( LOG_WARNING , " Unable to set normal priority \n " ) ;
return - 1 ;
}
}
# endif
1999-12-19 22:38:55 +00:00
return 0 ;
}
2002-05-14 14:43:52 +00:00
static char * _argv [ 256 ] ;
static int shuttingdown = 0 ;
static void quit_handler ( int num , int nice , 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 ;
if ( safeshutdown ) {
shuttingdown = 1 ;
if ( ! nice ) {
/* Begin shutdown routine, hanging up active channels */
ast_begin_shutdown ( 1 ) ;
if ( option_verbose & & option_console )
ast_verbose ( " Beginning asterisk %s.... \n " , restart ? " restart " : " shutdown " ) ;
time ( & s ) ;
for ( ; ; ) {
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 {
if ( nice < 2 )
ast_begin_shutdown ( 0 ) ;
if ( option_verbose & & option_console )
ast_verbose ( " Waiting for inactivity to perform %s... \n " , restart ? " restart " : " halt " ) ;
for ( ; ; ) {
if ( ! ast_active_channels ( ) )
break ;
if ( ! shuttingdown )
break ;
sleep ( 1 ) ;
}
}
if ( ! shuttingdown ) {
if ( option_verbose & & option_console )
ast_verbose ( " Asterisk %s cancelled. \n " , restart ? " restart " : " shutdown " ) ;
return ;
}
}
2001-05-09 03:11:22 +00:00
if ( option_console | | option_remote ) {
if ( getenv ( " HOME " ) )
snprintf ( filename , sizeof ( filename ) , " %s/.asterisk_history " , getenv ( " HOME " ) ) ;
if ( strlen ( 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
}
1999-11-15 04:57:28 +00:00
/* Called on exit */
2001-05-09 03:11:22 +00:00
if ( option_verbose & & option_console )
2002-05-14 14:43:52 +00:00
ast_verbose ( " Asterisk %s ending (%d). \n " , ast_active_channels ( ) ? " uncleanly " : " cleanly " , num ) ;
1999-11-15 04:57:28 +00:00
else if ( option_debug )
ast_log ( LOG_DEBUG , " 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 ) {
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
2002-09-12 03:22:07 +00:00
ast_socket = - 1 ;
}
2001-05-09 03:11:22 +00:00
if ( ast_consock > - 1 )
close ( ast_consock ) ;
if ( ast_socket > - 1 )
2003-02-06 06:15:25 +00:00
unlink ( ( char * ) ast_config_AST_SOCKET ) ;
2003-07-09 13:45:59 +00:00
if ( ! option_remote ) unlink ( ( char * ) ast_config_AST_PID ) ;
2002-05-14 14:43:52 +00:00
printf ( term_quit ( ) ) ;
if ( restart ) {
if ( option_verbose | | option_console )
ast_verbose ( " Preparing for Asterisk restart... \n " ) ;
/* Mark all FD's for closing on exec */
for ( x = 3 ; x < 32768 ; x + + ) {
fcntl ( x , F_SETFD , FD_CLOEXEC ) ;
}
if ( option_verbose | | option_console )
ast_verbose ( " Restarting Asterisk NOW... \n " ) ;
execvp ( _argv [ 0 ] , _argv ) ;
} else
exit ( 0 ) ;
}
static void __quit_handler ( int num )
{
quit_handler ( num , 0 , 1 , 0 ) ;
1999-11-15 04:57:28 +00:00
}
1999-12-19 22:38:55 +00:00
static pthread_t consolethread = - 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 ;
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
}
2003-03-16 22:37:31 +00:00
static void console_verboser ( const char * s , int pos , int replace , int complete )
1999-12-19 22:38:55 +00:00
{
2002-05-14 14:43:52 +00:00
char tmp [ 80 ] ;
2003-06-27 23:02:52 +00:00
const char * c = NULL ;
1999-12-19 22:38:55 +00:00
/* Return to the beginning of the line */
2002-05-14 14:43:52 +00:00
if ( ! pos ) {
1999-12-19 22:38:55 +00:00
fprintf ( stdout , " \r " ) ;
2003-06-27 23:02:52 +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 ) ) )
2002-05-14 14:43:52 +00:00
fputs ( tmp , stdout ) ;
}
2003-06-27 23:02:52 +00:00
if ( c )
fputs ( c + pos , stdout ) ;
else
fputs ( s + pos , stdout ) ;
2000-01-02 20:59:00 +00:00
fflush ( stdout ) ;
1999-12-19 22:38:55 +00:00
if ( complete )
/* Wake up a select()ing console */
2002-09-12 03:22:07 +00:00
if ( consolethread > - 1 )
pthread_kill ( consolethread , SIGURG ) ;
1999-12-19 22:38:55 +00:00
}
static void consolehandler ( char * s )
{
2002-05-14 14:43:52 +00:00
printf ( term_end ( ) ) ;
fflush ( stdout ) ;
1999-12-19 22:38:55 +00:00
/* Called when readline data is available */
if ( s & & strlen ( s ) )
2003-02-06 06:15:25 +00:00
ast_el_add_history ( s ) ;
2000-01-02 20:59:00 +00:00
/* Give the console access to the shell */
if ( s ) {
if ( s [ 0 ] = = ' ! ' ) {
if ( s [ 1 ] )
system ( s + 1 ) ;
else
system ( getenv ( " SHELL " ) ? getenv ( " SHELL " ) : " /bin/sh " ) ;
} else
1999-12-19 22:38:55 +00:00
ast_cli_command ( STDOUT_FILENO , s ) ;
2000-01-02 20:59:00 +00:00
if ( ! strcasecmp ( s , " help " ) )
fprintf ( stdout , " !<command> Executes a given shell command \n " ) ;
} else
fprintf ( stdout , " \n Use \" quit \" to exit \n " ) ;
1999-12-19 22:38:55 +00:00
}
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 ;
2001-05-09 03:11:22 +00:00
/* Called when readline data is available */
if ( s & & strlen ( s ) )
2003-02-06 06:15:25 +00:00
ast_el_add_history ( s ) ;
2001-05-09 03:11:22 +00:00
/* Give the console access to the shell */
if ( s ) {
if ( s [ 0 ] = = ' ! ' ) {
if ( s [ 1 ] )
system ( s + 1 ) ;
else
system ( getenv ( " SHELL " ) ? getenv ( " SHELL " ) : " /bin/sh " ) ;
2003-02-06 06:15:25 +00:00
ret = 1 ;
}
if ( ! strcasecmp ( s , " help " ) ) {
2001-05-09 03:11:22 +00:00
fprintf ( stdout , " !<command> Executes a given shell command \n " ) ;
2003-02-06 06:15:25 +00:00
ret = 0 ;
}
if ( ! strcasecmp ( s , " quit " ) ) {
quit_handler ( 0 , 0 , 0 , 0 ) ;
ret = 1 ;
}
if ( ! strcasecmp ( s , " exit " ) ) {
2002-05-14 14:43:52 +00:00
quit_handler ( 0 , 0 , 0 , 0 ) ;
2003-02-06 06:15:25 +00:00
ret = 1 ;
}
2001-05-09 03:11:22 +00:00
} else
fprintf ( stdout , " \n Use \" quit \" to exit \n " ) ;
2003-02-06 06:15:25 +00:00
return ret ;
2001-05-09 03:11:22 +00:00
}
1999-12-19 22:38:55 +00:00
static char quit_help [ ] =
" Usage: quit \n "
" Exits Asterisk. \n " ;
2002-05-14 14:43:52 +00:00
static char abort_halt_help [ ] =
" Usage: abort shutdown \n "
" Causes Asterisk to abort an executing shutdown or restart, and resume normal \n "
" call operations. \n " ;
static char shutdown_now_help [ ] =
2003-02-06 06:15:25 +00:00
" Usage: stop now \n "
2002-05-14 14:43:52 +00:00
" Shuts down a running Asterisk immediately, hanging up all active calls . \n " ;
static char shutdown_gracefully_help [ ] =
2003-02-06 06:15:25 +00:00
" Usage: stop gracefully \n "
2002-05-14 14:43:52 +00:00
" Causes Asterisk to not accept new calls, and exit when all \n "
" active calls have terminated normally. \n " ;
2003-04-23 16:24:09 +00:00
static char shutdown_when_convenient_help [ ] =
" Usage: stop when convenient \n "
" Causes Asterisk to perform a shutdown when all active calls have ended. \n " ;
2002-05-14 14:43:52 +00:00
static char restart_now_help [ ] =
" Usage: restart now \n "
" Causes Asterisk to hangup all calls and exec() itself performing a cold. \n "
" restart. \n " ;
static char restart_gracefully_help [ ] =
" Usage: restart gracefully \n "
" Causes Asterisk to stop accepting new calls and exec() itself performing a cold. \n "
" restart when all active calls have ended. \n " ;
static char restart_when_convenient_help [ ] =
" Usage: restart when convenient \n "
" Causes Asterisk to perform a cold restart when all active calls have ended. \n " ;
2001-05-09 03:11:22 +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
2003-02-06 06:15:25 +00:00
static int no_more_quit ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 1 )
return RESULT_SHOWUSAGE ;
ast_cli ( fd , " The QUIT and EXIT commands may no longer be used to shutdown the PBX. \n "
" Please use STOP NOW instead, if you wish to shutdown the PBX. \n " ) ;
return RESULT_SUCCESS ;
}
2002-05-14 14:43:52 +00:00
static int handle_shutdown_now ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 2 )
return RESULT_SHOWUSAGE ;
quit_handler ( 0 , 0 /* Not nice */ , 1 /* safely */ , 0 /* not restart */ ) ;
return RESULT_SUCCESS ;
}
static int handle_shutdown_gracefully ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 2 )
return RESULT_SHOWUSAGE ;
quit_handler ( 0 , 1 /* nicely */ , 1 /* safely */ , 0 /* no restart */ ) ;
return RESULT_SUCCESS ;
}
2003-04-23 16:24:09 +00:00
static int handle_shutdown_when_convenient ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 3 )
return RESULT_SHOWUSAGE ;
quit_handler ( 0 , 2 /* really nicely */ , 1 /* safely */ , 0 /* don't restart */ ) ;
return RESULT_SUCCESS ;
}
2002-05-14 14:43:52 +00:00
static int handle_restart_now ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 2 )
return RESULT_SHOWUSAGE ;
quit_handler ( 0 , 0 /* not nicely */ , 1 /* safely */ , 1 /* restart */ ) ;
return RESULT_SUCCESS ;
}
static int handle_restart_gracefully ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 2 )
return RESULT_SHOWUSAGE ;
quit_handler ( 0 , 1 /* nicely */ , 1 /* safely */ , 1 /* restart */ ) ;
return RESULT_SUCCESS ;
}
static int handle_restart_when_convenient ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 3 )
return RESULT_SHOWUSAGE ;
quit_handler ( 0 , 2 /* really nicely */ , 1 /* safely */ , 1 /* restart */ ) ;
return RESULT_SUCCESS ;
}
static int handle_abort_halt ( int fd , int argc , char * argv [ ] )
{
if ( argc ! = 2 )
return RESULT_SHOWUSAGE ;
ast_cancel_shutdown ( ) ;
shuttingdown = 0 ;
1999-12-19 22:38:55 +00:00
return RESULT_SUCCESS ;
}
# define ASTERISK_PROMPT "*CLI> "
2001-05-09 03:11:22 +00:00
# define ASTERISK_PROMPT2 "%s*CLI> "
2002-05-14 14:43:52 +00:00
static struct ast_cli_entry aborthalt = { { " abort " , " halt " , NULL } , handle_abort_halt , " Cancel a running halt " , abort_halt_help } ;
2003-02-06 06:15:25 +00:00
static struct ast_cli_entry quit = { { " quit " , NULL } , no_more_quit , " Exit Asterisk " , quit_help } ;
static struct ast_cli_entry astexit = { { " exit " , NULL } , no_more_quit , " Exit Asterisk " , quit_help } ;
1999-12-19 22:38:55 +00:00
2003-02-06 06:15:25 +00:00
static struct ast_cli_entry astshutdownnow = { { " stop " , " now " , NULL } , handle_shutdown_now , " Shut down Asterisk imediately " , shutdown_now_help } ;
static struct ast_cli_entry astshutdowngracefully = { { " stop " , " gracefully " , NULL } , handle_shutdown_gracefully , " Gracefully shut down Asterisk " , shutdown_gracefully_help } ;
2003-04-23 16:24:09 +00:00
static struct ast_cli_entry astshutdownwhenconvenient = { { " stop " , " when " , " convenient " , NULL } , handle_shutdown_when_convenient , " Shut down Asterisk at empty call volume " , shutdown_when_convenient_help } ;
2002-05-14 14:43:52 +00:00
static struct ast_cli_entry astrestartnow = { { " restart " , " now " , NULL } , handle_restart_now , " Restart Asterisk immediately " , restart_now_help } ;
static struct ast_cli_entry astrestartgracefully = { { " restart " , " gracefully " , NULL } , handle_restart_gracefully , " Restart Asterisk gracefully " , restart_gracefully_help } ;
static struct ast_cli_entry astrestartwhenconvenient = { { " restart " , " when " , " convenient " , NULL } , handle_restart_when_convenient , " Restart Asterisk at empty call volume " , restart_when_convenient_help } ;
2001-05-09 03:11:22 +00:00
2003-02-06 06:15:25 +00:00
static int ast_el_read_char ( EditLine * el , char * cp )
{
int num_read = 0 ;
int lastpos = 0 ;
fd_set rfds ;
int res ;
int max ;
char buf [ 512 ] ;
for ( ; ; ) {
FD_ZERO ( & rfds ) ;
FD_SET ( ast_consock , & rfds ) ;
max = ast_consock ;
2003-06-23 16:40:12 +00:00
if ( ! option_exec ) {
FD_SET ( STDIN_FILENO , & rfds ) ;
if ( STDIN_FILENO > max )
max = STDIN_FILENO ;
}
2003-04-27 18:13:11 +00:00
res = ast_select ( max + 1 , & rfds , NULL , NULL , NULL ) ;
2003-02-06 06:15:25 +00:00
if ( res < 0 ) {
if ( errno = = EINTR )
continue ;
ast_log ( LOG_ERROR , " select failed: %s \n " , strerror ( errno ) ) ;
break ;
}
if ( FD_ISSET ( STDIN_FILENO , & rfds ) ) {
num_read = read ( STDIN_FILENO , cp , 1 ) ;
if ( num_read < 1 ) {
break ;
} else
return ( num_read ) ;
}
if ( FD_ISSET ( ast_consock , & rfds ) ) {
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 " ) ;
quit_handler ( 0 , 0 , 0 , 0 ) ;
}
buf [ res ] = ' \0 ' ;
2003-06-23 16:40:12 +00:00
if ( ! option_exec & & ! lastpos )
2003-02-06 06:15:25 +00:00
write ( STDOUT_FILENO , " \r " , 1 ) ;
write ( STDOUT_FILENO , buf , res ) ;
if ( ( buf [ res - 1 ] = = ' \n ' ) | | ( buf [ res - 2 ] = = ' \n ' ) ) {
2003-03-06 06:00:17 +00:00
* cp = CC_REFRESH ;
return ( 1 ) ;
2003-02-06 06:15:25 +00:00
} else {
lastpos = 1 ;
}
}
}
* cp = ' \0 ' ;
return ( 0 ) ;
}
static char * cli_prompt ( EditLine * el )
1999-12-19 22:38:55 +00:00
{
2003-04-08 13:45:36 +00:00
static char prompt [ 80 ] ;
2003-02-06 06:15:25 +00:00
if ( remotehostname )
snprintf ( prompt , sizeof ( prompt ) , ASTERISK_PROMPT2 , remotehostname ) ;
else
snprintf ( prompt , sizeof ( prompt ) , ASTERISK_PROMPT ) ;
2003-04-08 13:45:36 +00:00
return ( prompt ) ;
2003-02-06 06:15:25 +00:00
}
static char * * ast_el_strtoarr ( char * buf )
{
char * * match_list = NULL , * retstr ;
size_t match_list_len ;
int matches = 0 ;
match_list_len = 1 ;
while ( ( retstr = strsep ( & buf , " " ) ) ! = NULL ) {
if ( matches + 1 > = match_list_len ) {
match_list_len < < = 1 ;
match_list = realloc ( match_list , match_list_len * sizeof ( char * ) ) ;
}
match_list [ matches + + ] = retstr ;
}
if ( ! match_list )
return ( char * * ) NULL ;
if ( matches > = match_list_len )
match_list = realloc ( match_list , ( match_list_len + 1 ) * sizeof ( char * ) ) ;
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 ;
qsort ( & matches [ 0 ] , ( size_t ) ( len + 1 ) , sizeof ( char * ) , ast_el_sort_compare ) ;
for ( ; count > 0 ; count - - ) {
numoutputline = 0 ;
for ( i = 0 ; i < limit & & matches [ idx ] ; i + + , idx + + ) {
/* Don't print dupes */
if ( ( matches [ idx + 1 ] ! = NULL & & strcmp ( matches [ idx ] , matches [ idx + 1 ] ) = = 0 ) ) {
i - - ;
continue ;
}
numoutput + + ; numoutputline + + ;
fprintf ( stdout , " %-*s " , max , matches [ idx ] ) ;
}
if ( numoutputline > 0 )
fprintf ( stdout , " \n " ) ;
}
return numoutput ;
1999-12-19 22:38:55 +00:00
}
2003-02-06 06:15:25 +00:00
static char * cli_complete ( EditLine * el , int ch )
2001-05-09 03:11:22 +00:00
{
2003-02-06 06:15:25 +00:00
int len = 0 ;
char * ptr ;
int nummatches = 0 ;
char * * matches ;
int retval = CC_ERROR ;
2001-05-09 03:11:22 +00:00
char buf [ 1024 ] ;
int res ;
2003-02-06 06:15:25 +00:00
LineInfo * lf = ( LineInfo * ) el_line ( el ) ;
* 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 ;
if ( option_remote ) {
snprintf ( buf , sizeof ( buf ) , " _COMMAND NUMMATCHES \" %s \" \" %s \" " , lf - > buffer , ptr ) ;
fdprint ( ast_consock , buf ) ;
res = read ( ast_consock , buf , sizeof ( buf ) ) ;
buf [ res ] = ' \0 ' ;
nummatches = atoi ( buf ) ;
if ( nummatches > 0 ) {
snprintf ( buf , sizeof ( buf ) , " _COMMAND MATCHESARRAY \" %s \" \" %s \" " , lf - > buffer , ptr ) ;
fdprint ( ast_consock , buf ) ;
res = read ( ast_consock , buf , sizeof ( buf ) ) ;
buf [ res ] = ' \0 ' ;
matches = ast_el_strtoarr ( buf ) ;
} else
matches = ( char * * ) NULL ;
} else {
nummatches = ast_cli_generatornummatches ( ( char * ) lf - > buffer , ptr ) ;
matches = ast_cli_completion_matches ( ( char * ) lf - > buffer , ptr ) ;
}
if ( matches ) {
int i ;
int matches_num , maxlen , match_len ;
if ( matches [ 0 ] [ 0 ] ! = ' \0 ' ) {
el_deletestr ( el , ( int ) len ) ;
el_insertstr ( el , matches [ 0 ] ) ;
retval = CC_REFRESH ;
}
if ( nummatches = = 1 ) {
/* Found an exact match */
2003-04-08 13:45:36 +00:00
el_insertstr ( el , " " ) ;
2003-02-06 06:15:25 +00:00
retval = CC_REFRESH ;
} else {
/* Must be more than one match */
for ( i = 1 , maxlen = 0 ; matches [ i ] ; i + + ) {
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 {
2003-04-08 13:45:36 +00:00
el_insertstr ( el , " " ) ;
2003-02-06 06:15:25 +00:00
retval = CC_REFRESH ;
}
}
2003-04-08 13:45:36 +00:00
free ( matches ) ;
2003-02-06 06:15:25 +00:00
}
return ( char * ) retval ;
}
static int ast_el_initialize ( void )
{
HistEvent ev ;
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 ) ;
el_set ( el , EL_EDITOR , " emacs " ) ;
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 ) ;
return 0 ;
}
static int ast_el_add_history ( char * buf )
{
HistEvent ev ;
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
return ( history ( el_hist , & ev , H_ENTER , buf ) ) ;
}
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 )
{
char buf [ 256 ] ;
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 ) ) {
fgets ( buf , sizeof ( buf ) , f ) ;
if ( ! strcmp ( buf , " _HiStOrY_V2_ \n " ) )
continue ;
if ( ( ret = ast_el_add_history ( buf ) ) = = - 1 )
break ;
}
fclose ( f ) ;
return ret ;
2001-05-09 03:11:22 +00:00
}
static void ast_remotecontrol ( char * data )
{
char buf [ 80 ] ;
int res ;
char filename [ 80 ] = " " ;
char * hostname ;
char * cpid ;
char * version ;
int pid ;
char tmp [ 80 ] ;
2003-02-06 06:15:25 +00:00
char * stringp = NULL ;
char * ebuf ;
int num = 0 ;
2001-05-09 03:11:22 +00:00
read ( ast_consock , buf , sizeof ( buf ) ) ;
2003-02-06 06:15:25 +00:00
if ( data )
write ( ast_consock , data , strlen ( data ) + 1 ) ;
stringp = buf ;
hostname = strsep ( & stringp , " / " ) ;
cpid = strsep ( & stringp , " / " ) ;
version = strsep ( & stringp , " / " ) ;
2001-05-09 03:11:22 +00:00
if ( ! version )
version = " <Version Unknown> " ;
2003-02-06 06:15:25 +00:00
stringp = hostname ;
strsep ( & stringp , " . " ) ;
2001-05-09 03:11:22 +00:00
if ( cpid )
pid = atoi ( cpid ) ;
else
pid = - 1 ;
snprintf ( tmp , sizeof ( tmp ) , " set verbose atleast %d " , option_verbose ) ;
fdprint ( ast_consock , tmp ) ;
ast_verbose ( " Connected to Asterisk %s currently running on %s (pid = %d) \n " , version , hostname , pid ) ;
2003-02-06 06:15:25 +00:00
remotehostname = hostname ;
2001-05-09 03:11:22 +00:00
if ( getenv ( " HOME " ) )
snprintf ( filename , sizeof ( filename ) , " %s/.asterisk_history " , getenv ( " HOME " ) ) ;
2003-02-06 06:15:25 +00:00
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
el_set ( el , EL_GETCFN , ast_el_read_char ) ;
2001-05-09 03:11:22 +00:00
if ( strlen ( filename ) )
2003-02-06 06:15:25 +00:00
ast_el_read_history ( filename ) ;
2002-05-14 14:43:52 +00:00
ast_cli_register ( & quit ) ;
2003-02-06 06:15:25 +00:00
ast_cli_register ( & astexit ) ;
2002-05-14 14:43:52 +00:00
#if 0
ast_cli_register ( & astshutdown ) ;
# endif
2003-06-23 16:40:12 +00:00
if ( option_exec & & data ) { /* hack to print output then exit if asterisk -rx is used */
char tempchar ;
ast_el_read_char ( el , & tempchar ) ;
return ;
}
2001-05-09 03:11:22 +00:00
for ( ; ; ) {
2003-02-06 06:15:25 +00:00
ebuf = ( char * ) el_gets ( el , & num ) ;
if ( ebuf & & strlen ( ebuf ) ) {
if ( ebuf [ strlen ( ebuf ) - 1 ] = = ' \n ' )
ebuf [ strlen ( ebuf ) - 1 ] = ' \0 ' ;
if ( ! remoteconsolehandler ( ebuf ) ) {
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 " ) ;
}
2003-02-06 06:15:25 +00:00
static int show_cli_help ( void ) {
2002-09-12 03:22:07 +00:00
printf ( " Asterisk " ASTERISK_VERSION " , Copyright (C) 2000-2002, Digium. \n " ) ;
printf ( " Usage: asterisk [OPTIONS] \n " ) ;
printf ( " Valid Options: \n " ) ;
printf ( " -h This help screen \n " ) ;
printf ( " -r Connect to Asterisk on this machine \n " ) ;
printf ( " -f Do not fork \n " ) ;
printf ( " -n Disable console colorization \n " ) ;
printf ( " -p Run as pseudo-realtime thread \n " ) ;
printf ( " -v Increase verbosity (multiple v's = more verbose) \n " ) ;
printf ( " -q Quiet mode (supress output) \n " ) ;
2003-02-06 06:15:25 +00:00
printf ( " -g Dump core in case of a crash \n " ) ;
2002-09-12 03:22:07 +00:00
printf ( " -x <cmd> Execute command <cmd> (only valid with -r) \n " ) ;
printf ( " -i Initializie crypto keys at startup \n " ) ;
printf ( " -c Provide console CLI \n " ) ;
printf ( " -d Enable extra debugging \n " ) ;
printf ( " \n " ) ;
return 0 ;
}
2003-03-16 22:37:31 +00:00
static void ast_readconfig ( void ) {
2003-02-06 06:15:25 +00:00
struct ast_config * cfg ;
struct ast_variable * v ;
char * config = ASTCONFPATH ;
if ( option_overrideconfig = = 1 ) {
cfg = ast_load ( ( char * ) ast_config_AST_CONFIG_FILE ) ;
} else {
cfg = ast_load ( config ) ;
}
/* init with buildtime config */
strncpy ( ( char * ) ast_config_AST_CONFIG_DIR , AST_CONFIG_DIR , sizeof ( ast_config_AST_CONFIG_DIR ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_SPOOL_DIR , AST_SPOOL_DIR , sizeof ( ast_config_AST_SPOOL_DIR ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_MODULE_DIR , AST_MODULE_DIR , sizeof ( ast_config_AST_VAR_DIR ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_VAR_DIR , AST_VAR_DIR , sizeof ( ast_config_AST_VAR_DIR ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_LOG_DIR , AST_LOG_DIR , sizeof ( ast_config_AST_LOG_DIR ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_AGI_DIR , AST_AGI_DIR , sizeof ( ast_config_AST_AGI_DIR ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_DB , AST_DB , sizeof ( ast_config_AST_DB ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_KEY_DIR , AST_KEY_DIR , sizeof ( ast_config_AST_KEY_DIR ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_PID , AST_PID , sizeof ( ast_config_AST_PID ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_SOCKET , AST_SOCKET , sizeof ( ast_config_AST_SOCKET ) - 1 ) ;
strncpy ( ( char * ) ast_config_AST_RUN_DIR , AST_RUN_DIR , sizeof ( ast_config_AST_RUN_DIR ) - 1 ) ;
/* no asterisk.conf? no problem, use buildtime config! */
if ( ! cfg ) {
return ;
}
v = ast_variable_browse ( cfg , " directories " ) ;
while ( v ) {
if ( ! strcasecmp ( v - > name , " astetcdir " ) ) {
strncpy ( ( char * ) ast_config_AST_CONFIG_DIR , v - > value , sizeof ( ast_config_AST_CONFIG_DIR ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " astspooldir " ) ) {
strncpy ( ( char * ) ast_config_AST_SPOOL_DIR , v - > value , sizeof ( ast_config_AST_SPOOL_DIR ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " astvarlibdir " ) ) {
strncpy ( ( char * ) ast_config_AST_VAR_DIR , v - > value , sizeof ( ast_config_AST_VAR_DIR ) - 1 ) ;
snprintf ( ( char * ) ast_config_AST_DB , sizeof ( ast_config_AST_DB ) - 1 , " %s/%s " , v - > value , " astdb " ) ;
} else if ( ! strcasecmp ( v - > name , " astlogdir " ) ) {
strncpy ( ( char * ) ast_config_AST_LOG_DIR , v - > value , sizeof ( ast_config_AST_LOG_DIR ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " astagidir " ) ) {
strncpy ( ( char * ) ast_config_AST_AGI_DIR , v - > value , sizeof ( ast_config_AST_AGI_DIR ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " astrundir " ) ) {
snprintf ( ( char * ) ast_config_AST_PID , sizeof ( ast_config_AST_PID ) - 1 , " %s/%s " , v - > value , " asterisk.pid " ) ;
snprintf ( ( char * ) ast_config_AST_SOCKET , sizeof ( ast_config_AST_SOCKET ) - 1 , " %s/%s " , v - > value , " asterisk.ctl " ) ;
strncpy ( ( char * ) ast_config_AST_RUN_DIR , v - > value , sizeof ( ast_config_AST_RUN_DIR ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " astmoddir " ) ) {
strncpy ( ( char * ) ast_config_AST_MODULE_DIR , v - > value , sizeof ( ast_config_AST_MODULE_DIR ) - 1 ) ;
}
v = v - > next ;
}
ast_destroy ( cfg ) ;
}
1999-11-15 04:57:28 +00:00
int main ( int argc , char * argv [ ] )
{
char c ;
1999-12-19 22:38:55 +00:00
char filename [ 80 ] = " " ;
2001-03-22 04:14:04 +00:00
char hostname [ 256 ] ;
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 ;
char * buf ;
2001-05-09 03:11:22 +00:00
2002-05-14 14:43:52 +00:00
/* Remember original args for restart */
if ( argc > sizeof ( _argv ) / sizeof ( _argv [ 0 ] ) - 1 ) {
fprintf ( stderr , " Truncating argument size to %d \n " , sizeof ( _argv ) / sizeof ( _argv [ 0 ] ) - 1 ) ;
argc = sizeof ( _argv ) / sizeof ( _argv [ 0 ] ) - 1 ;
}
for ( x = 0 ; x < argc ; x + + )
_argv [ x ] = argv [ x ] ;
_argv [ x ] = NULL ;
2001-03-22 04:14:04 +00:00
if ( gethostname ( hostname , sizeof ( hostname ) ) )
2001-12-25 21:12:07 +00:00
strncpy ( hostname , " <Unknown> " , sizeof ( hostname ) - 1 ) ;
2001-05-09 03:11:22 +00:00
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 ( ) ;
2001-12-25 21:12:07 +00:00
tdd_init ( ) ;
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 if we're root */
2003-02-06 06:15:25 +00:00
/*
1999-11-15 04:57:28 +00:00
if ( geteuid ( ) ) {
ast_log ( LOG_ERROR , " Must be run as root \n " ) ;
exit ( 1 ) ;
}
2003-02-06 06:15:25 +00:00
*/
1999-11-15 04:57:28 +00:00
/* Check for options */
2003-02-06 06:15:25 +00:00
while ( ( c = getopt ( argc , argv , " hfdvqprgcinx:C: " ) ) ! = EOF ) {
1999-11-15 04:57:28 +00:00
switch ( c ) {
case ' d ' :
option_debug + + ;
option_nofork + + ;
1999-12-19 22:38:55 +00:00
break ;
2000-01-02 20:59:00 +00:00
case ' c ' :
option_console + + ;
option_nofork + + ;
2001-03-22 04:14:04 +00:00
break ;
2001-05-09 03:11:22 +00:00
case ' f ' :
option_nofork + + ;
break ;
2002-05-14 14:43:52 +00:00
case ' n ' :
option_nocolor + + ;
break ;
2001-05-09 03:11:22 +00:00
case ' r ' :
option_remote + + ;
option_nofork + + ;
break ;
1999-12-19 22:38:55 +00:00
case ' p ' :
option_highpriority + + ;
1999-11-15 04:57:28 +00:00
break ;
case ' v ' :
option_verbose + + ;
2000-01-02 20:59:00 +00:00
option_nofork + + ;
1999-11-15 04:57:28 +00:00
break ;
case ' q ' :
option_quiet + + ;
break ;
2001-05-09 03:11:22 +00:00
case ' x ' :
option_exec + + ;
xarg = optarg ;
break ;
2003-02-06 06:15:25 +00:00
case ' C ' :
strncpy ( ( char * ) ast_config_AST_CONFIG_FILE , optarg , sizeof ( ast_config_AST_CONFIG_FILE ) ) ;
option_overrideconfig + + ;
break ;
2001-12-25 21:12:07 +00:00
case ' i ' :
option_initcrypto + + ;
break ;
2003-02-06 06:15:25 +00:00
case ' g ' :
option_dumpcore + + ;
break ;
2002-09-12 03:22:07 +00:00
case ' h ' :
show_cli_help ( ) ;
exit ( 0 ) ;
1999-11-15 04:57:28 +00:00
case ' ? ' :
exit ( 1 ) ;
}
}
2002-05-14 14:43:52 +00:00
2003-02-06 06:15:25 +00:00
if ( option_dumpcore ) {
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 ) ) ;
}
}
2002-05-14 14:43:52 +00:00
term_init ( ) ;
printf ( term_end ( ) ) ;
fflush ( stdout ) ;
2003-02-06 06:15:25 +00:00
if ( option_console & & ! option_verbose )
ast_verbose ( " [ Reading Master Configuration ] " ) ;
ast_readconfig ( ) ;
2003-04-16 13:43:11 +00:00
if ( option_console ) {
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
2003-02-06 06:15:25 +00:00
2003-04-16 13:43:11 +00:00
if ( strlen ( filename ) )
ast_el_read_history ( filename ) ;
}
2003-02-06 06:15:25 +00:00
2001-05-09 03:11:22 +00:00
if ( ast_tryconnect ( ) ) {
/* One is already running */
if ( option_remote ) {
if ( option_exec ) {
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 ) ;
}
2002-05-14 14:43:52 +00:00
printf ( term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
ast_register_verbose ( console_verboser ) ;
ast_verbose ( " Asterisk " ASTERISK_VERSION " , Copyright (C) 1999-2001 Linux Support Services, Inc. \n " ) ;
ast_verbose ( " Written by Mark Spencer <markster@linux-support.net> \n " ) ;
ast_verbose ( " ========================================================================= \n " ) ;
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 {
2003-02-06 06:15:25 +00:00
ast_log ( LOG_ERROR , " Asterisk already running on %s. Use 'asterisk -r' to connect. \n " , ( char * ) ast_config_AST_SOCKET ) ;
2002-05-14 14:43:52 +00:00
printf ( term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
exit ( 1 ) ;
}
} else if ( option_remote | | option_exec ) {
ast_log ( LOG_ERROR , " Unable to connect to remote asterisk \n " ) ;
2002-05-14 14:43:52 +00:00
printf ( 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 */
2003-02-06 06:15:25 +00:00
unlink ( ( char * ) ast_config_AST_PID ) ;
f = fopen ( ( char * ) ast_config_AST_PID , " w " ) ;
2002-09-12 03:22:07 +00:00
if ( f ) {
fprintf ( f , " %d \n " , getpid ( ) ) ;
fclose ( f ) ;
} else
2003-02-06 06:15:25 +00:00
ast_log ( LOG_WARNING , " Unable to open pid file '%s': %s \n " , ( char * ) ast_config_AST_PID , strerror ( errno ) ) ;
2001-12-25 21:12:07 +00:00
if ( ! option_verbose & & ! option_debug & & ! option_nofork & & ! option_console ) {
2002-09-12 03:22:07 +00:00
# if 1
daemon ( 0 , 0 ) ;
# else
2001-05-09 03:11:22 +00:00
pid = fork ( ) ;
if ( pid < 0 ) {
ast_log ( LOG_ERROR , " Unable to fork(): %s \n " , strerror ( errno ) ) ;
2002-05-14 14:43:52 +00:00
printf ( term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
exit ( 1 ) ;
}
if ( pid )
exit ( 0 ) ;
2002-09-12 03:22:07 +00:00
# endif
2001-05-09 03:11:22 +00:00
}
2001-12-25 21:12:07 +00:00
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 ) ;
if ( option_console | | option_verbose | | option_remote )
ast_register_verbose ( console_verboser ) ;
1999-11-15 04:57:28 +00:00
/* Print a welcome message if desired */
2000-01-02 20:59:00 +00:00
if ( option_verbose | | option_console ) {
2001-05-09 03:11:22 +00:00
ast_verbose ( " Asterisk " ASTERISK_VERSION " , Copyright (C) 1999-2001 Linux Support Services, Inc. \n " ) ;
1999-11-15 04:57:28 +00:00
ast_verbose ( " Written by Mark Spencer <markster@linux-support.net> \n " ) ;
ast_verbose ( " ========================================================================= \n " ) ;
}
2000-01-02 20:59:00 +00:00
if ( option_console & & ! option_verbose )
ast_verbose ( " [ Booting... " ) ;
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 ) ;
signal ( SIGPIPE , pipe_handler ) ;
2002-05-14 14:43:52 +00:00
if ( set_priority ( option_highpriority ) ) {
printf ( term_quit ( ) ) ;
2001-03-22 04:14:04 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
if ( init_logger ( ) ) {
printf ( term_quit ( ) ) ;
1999-11-15 04:57:28 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
2002-09-12 03:22:07 +00:00
if ( init_manager ( ) ) {
printf ( term_quit ( ) ) ;
exit ( 1 ) ;
}
2003-05-16 02:50:46 +00:00
ast_rtp_init ( ) ;
2002-05-14 14:43:52 +00:00
if ( ast_image_init ( ) ) {
printf ( term_quit ( ) ) ;
2001-10-11 18:51:39 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
if ( load_pbx ( ) ) {
printf ( term_quit ( ) ) ;
1999-11-15 04:57:28 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
if ( load_modules ( ) ) {
printf ( term_quit ( ) ) ;
1999-11-15 04:57:28 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
if ( init_framer ( ) ) {
printf ( term_quit ( ) ) ;
2001-10-11 18:51:39 +00:00
exit ( 1 ) ;
2002-05-14 14:43:52 +00:00
}
2003-02-06 06:15:25 +00:00
if ( astdb_init ( ) ) {
printf ( term_quit ( ) ) ;
exit ( 1 ) ;
}
2003-05-01 04:29:25 +00:00
if ( ast_enum_init ( ) ) {
printf ( term_quit ( ) ) ;
exit ( 1 ) ;
}
1999-11-15 04:57:28 +00:00
/* We might have the option of showing a console, but for now just
do nothing . . . */
2000-01-02 20:59:00 +00:00
if ( option_console & & ! option_verbose )
ast_verbose ( " ] \n " ) ;
if ( option_verbose | | option_console )
2002-05-14 14:43:52 +00:00
ast_verbose ( term_color ( tmp , " Asterisk Ready. \n " , COLOR_BRWHITE , COLOR_BLACK , sizeof ( tmp ) ) ) ;
2000-01-02 20:59:00 +00:00
fully_booted = 1 ;
2001-05-09 03:11:22 +00:00
pthread_sigmask ( SIG_UNBLOCK , & sigs , NULL ) ;
2003-04-28 19:58:43 +00:00
# ifdef __AST_DEBUG_MALLOC
__ast_mm_init ( ) ;
# endif
2003-05-02 15:37:34 +00:00
time ( & ast_startuptime ) ;
2002-05-14 14:43:52 +00:00
ast_cli_register ( & astshutdownnow ) ;
ast_cli_register ( & astshutdowngracefully ) ;
ast_cli_register ( & astrestartnow ) ;
ast_cli_register ( & astrestartgracefully ) ;
ast_cli_register ( & astrestartwhenconvenient ) ;
2003-04-23 16:24:09 +00:00
ast_cli_register ( & astshutdownwhenconvenient ) ;
2002-05-14 14:43:52 +00:00
ast_cli_register ( & aborthalt ) ;
2000-01-02 20:59:00 +00:00
if ( option_console ) {
/* Console stuff now... */
/* Register our quit function */
2000-10-25 23:22:50 +00:00
char title [ 256 ] ;
set_icon ( " Asterisk " ) ;
2001-05-09 03:11:22 +00:00
snprintf ( title , sizeof ( title ) , " Asterisk Console on '%s' (pid %d) " , hostname , mainpid ) ;
2000-10-25 23:22:50 +00:00
set_title ( title ) ;
2000-01-02 20:59:00 +00:00
ast_cli_register ( & quit ) ;
2003-02-06 06:15:25 +00:00
ast_cli_register ( & astexit ) ;
2000-01-02 20:59:00 +00:00
consolethread = pthread_self ( ) ;
2003-02-06 06:15:25 +00:00
2003-05-22 14:24:06 +00:00
for ( ; ; ) {
buf = ( char * ) el_gets ( el , & num ) ;
if ( buf ) {
if ( buf [ strlen ( buf ) - 1 ] = = ' \n ' )
buf [ strlen ( buf ) - 1 ] = ' \0 ' ;
consolehandler ( ( char * ) buf ) ;
} else
ast_cli ( STDOUT_FILENO , " \n Use EXIT or QUIT to exist, or STOP NOW to shutdown Asterisk \n " ) ;
2003-02-06 06:15:25 +00:00
}
2000-01-02 20:59:00 +00:00
} else {
2001-12-25 21:12:07 +00:00
/* Do nothing */
2003-04-27 18:13:11 +00:00
ast_select ( 0 , NULL , NULL , NULL , NULL ) ;
2000-01-02 20:59:00 +00:00
}
1999-11-15 04:57:28 +00:00
return 0 ;
}