📄 asterisk.c
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer <markster@digium.com> * * 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. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//* Doxygenified Copyright Header *//*! * \mainpage Asterisk -- An Open Source Telephony Toolkit * * \par Developer Documentation for Asterisk * This is the main developer documentation for Asterisk. It is * generated by running "make progdocs". * \par Additional documentation * \arg \ref DevDoc * \arg \ref ConfigFiles * * \section copyright Copyright and author * * Copyright (C) 1999 - 2005, Digium, Inc. * Asterisk is a trade mark registered by Digium, Inc. * * \author Mark Spencer <markster@digium.com> * Also see \ref AstCREDITS * * \section license License * 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. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. * * \verbinclude LICENSE * *//*! \file \brief Top level source file for Asterisk - the Open Source PBX. Implementation of PBX core functions and CLI interface. */#include <unistd.h>#include <stdlib.h>#include <sys/time.h>#include <fcntl.h>#include <stdio.h>#include <signal.h>#include <sched.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/wait.h>#include <string.h>#include <errno.h>#include <ctype.h>#include <sys/resource.h>#include <grp.h>#include <pwd.h>#include <sys/stat.h>#include <regex.h>#ifdef linux#include <sys/prctl.h>#endif #if defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS)#include <netdb.h>#if defined(SOLARIS)extern int daemon(int, int); /* defined in libresolv of all places */#endif#endif#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 37419 $")#include "asterisk/logger.h"#include "asterisk/options.h"#include "asterisk/cli.h"#include "asterisk/channel.h"#include "asterisk/ulaw.h"#include "asterisk/alaw.h"#include "asterisk/callerid.h"#include "asterisk/module.h"#include "asterisk/image.h"#include "asterisk/tdd.h"#include "asterisk/term.h"#include "asterisk/manager.h"#include "asterisk/cdr.h"#include "asterisk/pbx.h"#include "asterisk/enum.h"#include "asterisk/rtp.h"#include "asterisk/app.h"#include "asterisk/lock.h"#include "asterisk/utils.h"#include "asterisk/file.h"#include "asterisk/io.h"#include "asterisk/lock.h"#include "editline/histedit.h"#include "asterisk/config.h"#include "asterisk/version.h"#include "asterisk/linkedlists.h"#include "asterisk/devicestate.h"#include "asterisk/compat.h"#include "asterisk/write_data_file.h"#include "asterisk/doxyref.h" /* Doxygen documentation */#include "defaults.h"#ifndef AF_LOCAL#define AF_LOCAL AF_UNIX#define PF_LOCAL PF_UNIX#endif#define AST_MAX_CONNECTS 128#define NUM_MSGS 64/*! \brief Welcome message when starting a CLI interface */#define WELCOME_MESSAGE \ ast_verbose("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2006 Digium, Inc. and others.\n"); \ ast_verbose("Created by Mark Spencer <markster@digium.com>\n"); \ ast_verbose("Asterisk comes with ABSOLUTELY NO WARRANTY; type 'show warranty' for details.\n"); \ ast_verbose("This is free software, with components licensed under the GNU General Public\n"); \ ast_verbose("License version 2 and other licenses; you are welcome to redistribute it under\n"); \ ast_verbose("certain conditions. Type 'show license' for details.\n"); \ ast_verbose("=========================================================================\n")/*! \defgroup main_options \brief Main configuration options from \ref Config_ast "asterisk.conf" or the operating system command line when starting Asterisk Some of them can be changed in the CLI *//*! @{ */int option_verbose=0; /*!< Verbosity level */int option_debug=0; /*!< Debug level */int option_exec_includes=0; /*!< Allow \#exec in config files? */int option_nofork=0; /*!< Do not fork */int option_quiet=0; /*!< Keep quiet */int option_console=0; /*!< Console mode, no background */int option_highpriority=0; /*!< Run in realtime Linux priority */int option_remote=0; /*!< Remote CLI */int option_exec=0; /*!< */int option_initcrypto=0; /*!< Initialize crypto keys for RSA auth */int option_nocolor; /*!< Don't use termcap colors */int option_dumpcore = 0; /*!< Dump core when failing */int option_cache_record_files = 0; /*!< Cache sound files */int option_timestamp = 0; /*!< Timestamp in logging */int option_overrideconfig = 0; /*!< */int option_reconnect = 0; /*!< */int option_transcode_slin = 1; /*!< */int option_maxcalls = 0; /*!< */double option_maxload = 0.0; /*!< Max load avg on system */int option_dontwarn = 0; /*!< */int option_priority_jumping = 1; /*!< Enable priority jumping as result value for apps */int option_transmit_silence_during_record = 0; /*!< Transmit silence during record() app *//*! @} */int fully_booted = 0;char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;char debug_filename[AST_FILENAME_MAX] = "";static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */int ast_mainpid;struct console { int fd; /*!< File descriptor */ int p[2]; /*!< Pipe */ pthread_t t; /*!< Thread of handler */};static struct ast_atexit { void (*func)(void); struct ast_atexit *next;} *atexits = NULL;AST_MUTEX_DEFINE_STATIC(atexitslock);time_t ast_startuptime;time_t ast_lastreloadtime;static History *el_hist = NULL;static EditLine *el = NULL;static char *remotehostname;struct console consoles[AST_MAX_CONNECTS];char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;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_MONITOR_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];char ast_config_AST_RUN_USER[AST_CONFIG_MAX_PATH];char ast_config_AST_RUN_GROUP[AST_CONFIG_MAX_PATH];char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";static char *_argv[256];static int shuttingdown = 0;static int restartnow = 0;static pthread_t consolethread = AST_PTHREADT_NULL;#if !defined(LOW_MEMORY)struct file_version { AST_LIST_ENTRY(file_version) list; const char *file; char *version;};static AST_LIST_HEAD_STATIC(file_versions, file_version);void ast_register_file_version(const char *file, const char *version){ struct file_version *new; char *work; size_t version_length; work = ast_strdupa(version); work = ast_strip(ast_strip_quoted(work, "$", "$")); version_length = strlen(work) + 1; new = calloc(1, sizeof(*new) + version_length); if (!new) return; new->file = file; new->version = (char *) new + sizeof(*new); memcpy(new->version, work, version_length); AST_LIST_LOCK(&file_versions); AST_LIST_INSERT_HEAD(&file_versions, new, list); AST_LIST_UNLOCK(&file_versions);}void ast_unregister_file_version(const char *file){ struct file_version *find; AST_LIST_LOCK(&file_versions); AST_LIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) { if (!strcasecmp(find->file, file)) { AST_LIST_REMOVE_CURRENT(&file_versions, list); break; } } AST_LIST_TRAVERSE_SAFE_END; AST_LIST_UNLOCK(&file_versions); if (find) free(find);}static char show_version_files_help[] = "Usage: show version files [like <pattern>]\n"" Shows 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";/*! CLI command to list module versions */static int handle_show_version_files(int fd, int argc, char *argv[]){#define FORMAT "%-25.25s %-40.40s\n" struct file_version *iterator; regex_t regexbuf; int havepattern = 0; int havename = 0; int count_files = 0; switch (argc) { case 5: if (!strcasecmp(argv[3], "like")) { if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) return RESULT_SHOWUSAGE; havepattern = 1; } else return RESULT_SHOWUSAGE; break; case 4: havename = 1; break; case 3: break; default: return RESULT_SHOWUSAGE; } ast_cli(fd, FORMAT, "File", "Revision"); ast_cli(fd, FORMAT, "----", "--------"); AST_LIST_LOCK(&file_versions); AST_LIST_TRAVERSE(&file_versions, iterator, list) { if (havename && strcasecmp(iterator->file, argv[3])) continue; if (havepattern && regexec(®exbuf, iterator->file, 0, NULL, 0)) continue; ast_cli(fd, FORMAT, iterator->file, iterator->version); count_files++; if (havename) break; } AST_LIST_UNLOCK(&file_versions); if (!havename) { ast_cli(fd, "%d files listed.\n", count_files); } if (havepattern) regfree(®exbuf); return RESULT_SUCCESS;#undef FORMAT}static char *complete_show_version_files(char *line, char *word, int pos, int state){ struct file_version *find; int which = 0; char *ret = NULL; int matchlen = strlen(word); if (pos != 3) return NULL; AST_LIST_LOCK(&file_versions); AST_LIST_TRAVERSE(&file_versions, find, list) { if (!strncasecmp(word, find->file, matchlen)) { if (++which > state) { ret = strdup(find->file); break; } } } AST_LIST_UNLOCK(&file_versions); return ret;}#endif /* ! LOW_MEMORY */int ast_register_atexit(void (*func)(void)){ int res = -1; struct ast_atexit *ae; ast_unregister_atexit(func); ae = malloc(sizeof(struct ast_atexit)); ast_mutex_lock(&atexitslock); if (ae) { memset(ae, 0, sizeof(struct ast_atexit)); ae->next = atexits; ae->func = func; atexits = ae; res = 0; } ast_mutex_unlock(&atexitslock); return res;}void ast_unregister_atexit(void (*func)(void)){ struct ast_atexit *ae, *prev = NULL; ast_mutex_lock(&atexitslock); ae = atexits; while(ae) { if (ae->func == func) { if (prev) prev->next = ae->next; else atexits = ae->next; break; } prev = ae; ae = ae->next; } ast_mutex_unlock(&atexitslock);}static int fdprint(int fd, const char *s){ return write(fd, s, strlen(s) + 1);}/*! NULL handler so we can collect the child exit status */static void null_sig_handler(int signal){}AST_MUTEX_DEFINE_STATIC(safe_system_lock);static unsigned int safe_system_level = 0;static void *safe_system_prev_handler;int ast_safe_system(const char *s){ pid_t pid; int x; int res; struct rusage rusage; int status; unsigned int level; /* keep track of how many ast_safe_system() functions are running at this moment */ 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); pid = fork(); if (pid == 0) { if (option_highpriority) ast_set_priority(0); /* Close file descriptors and launch system command */ for (x = STDERR_FILENO + 1; x < 4096; x++) close(x); execl("/bin/sh", "/bin/sh", "-c", s, NULL); exit(1); } else if (pid > 0) { for(;;) { res = wait4(pid, &status, 0, &rusage); if (res > -1) { res = WIFEXITED(status) ? WEXITSTATUS(status) : -1; break; } else if (errno != EINTR) break; } } else { ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno)); res = -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -