mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
Version 0.1.8 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@320 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
35
CHANGES
35
CHANGES
@@ -1,3 +1,38 @@
|
|||||||
|
Asterisk 0.1.8
|
||||||
|
-- Keep track of version information
|
||||||
|
-- Add -f to cause Asterisk not to fork
|
||||||
|
-- Keep important information in voicemail .txt file
|
||||||
|
-- Adtran Voice over Frame Relay updates
|
||||||
|
-- Implement option setting/querying of channel drivers
|
||||||
|
-- IAX performance improvements and protocol fixes
|
||||||
|
-- Substantial enhancement of console channel driver
|
||||||
|
-- Add IAX registration. Now IAX can dynamically register
|
||||||
|
-- Add flash-hook transfer on tormenta channels
|
||||||
|
-- Added Three Way Calling on tormenta channels
|
||||||
|
-- Start on concept of zombie channel
|
||||||
|
-- Add Call Waiting CallerID
|
||||||
|
-- Keep track of who registeres contexts, includes, and extensions
|
||||||
|
-- Added Call Waiting(tm), *67, *70, and *82 codes
|
||||||
|
-- Move parked calls into "parkedcalls" context by default
|
||||||
|
-- Allow dialplan to be displayed
|
||||||
|
-- Allow "=>" instead of just "=" to make instantiation clearer
|
||||||
|
-- Asterisk forks if called with no arguments
|
||||||
|
-- Add remote control by running asterisk -vvvc
|
||||||
|
-- Adjust verboseness with "set verbose" now
|
||||||
|
-- No longer requires libaudiofile
|
||||||
|
-- Install beep
|
||||||
|
-- Make PBX Config module reload extensions on SIGHUP
|
||||||
|
-- Allow modules to be reloaded when SIGHUP is received
|
||||||
|
-- Variables now contain line numbers
|
||||||
|
-- Make dialer send in band signalling
|
||||||
|
-- Add record application
|
||||||
|
-- Added PRI signalling to Tormenta driver
|
||||||
|
-- Allow use of BYEXTENSION in "Goto"
|
||||||
|
-- Allow adjustment of gains on tormenta channels
|
||||||
|
-- Added raw PCM file format support
|
||||||
|
-- Add U-law translator
|
||||||
|
-- Fix DTMF handling in bridge code
|
||||||
|
-- Fix access control with IAX
|
||||||
* Asterisk 0.1.7
|
* Asterisk 0.1.7
|
||||||
-- Update configuration files and add some missing sounds
|
-- Update configuration files and add some missing sounds
|
||||||
-- Added ability to include one context in another
|
-- Added ability to include one context in another
|
||||||
|
22
Makefile
22
Makefile
@@ -23,11 +23,14 @@ PROC=i586
|
|||||||
|
|
||||||
DEBUG=-g #-pg
|
DEBUG=-g #-pg
|
||||||
INCLUDE=-Iinclude -I../include
|
INCLUDE=-Iinclude -I../include
|
||||||
CFLAGS=-pipe -Wall -Werror -Wmissing-prototypes -Wmissing-declarations -fomit-frame-pointer -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT
|
CFLAGS=-pipe -Wall -Werror -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT
|
||||||
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||||
CFLAGS += -DDO_CRASH
|
ASTERISKVERSION=$(shell cat .version)
|
||||||
|
CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\"
|
||||||
|
CFLAGS+= -DDO_CRASH -DDEBUG_THREADS
|
||||||
|
CFLAGS+=# -fomit-frame-pointer
|
||||||
SUBDIRS=channels pbx apps codecs formats
|
SUBDIRS=channels pbx apps codecs formats
|
||||||
LIBS=-ldl -lpthread -lreadline -lncurses -lm # -lefence
|
LIBS=-ldl -lpthread -lreadline -lncurses -lm
|
||||||
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
|
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
|
||||||
translate.o file.o say.o pbx.o cli.o md5.o \
|
translate.o file.o say.o pbx.o cli.o md5.o \
|
||||||
ulaw.o callerid.o fskmodem.o asterisk.o
|
ulaw.o callerid.o fskmodem.o asterisk.o
|
||||||
@@ -46,7 +49,13 @@ _all: all
|
|||||||
|
|
||||||
all: asterisk subdirs
|
all: asterisk subdirs
|
||||||
|
|
||||||
asterisk: $(OBJS)
|
_version:
|
||||||
|
if [ -d CVS ]; then echo "CVS-`date +"%D-%T"`" > .version; fi
|
||||||
|
|
||||||
|
build.h:
|
||||||
|
./make_build_h
|
||||||
|
|
||||||
|
asterisk: _version build.h $(OBJS)
|
||||||
gcc -o asterisk -rdynamic $(OBJS) $(LIBS)
|
gcc -o asterisk -rdynamic $(OBJS) $(LIBS)
|
||||||
|
|
||||||
subdirs:
|
subdirs:
|
||||||
@@ -55,17 +64,20 @@ subdirs:
|
|||||||
clean:
|
clean:
|
||||||
for x in $(SUBDIRS); do $(MAKE) -C $$x clean || exit 1 ; done
|
for x in $(SUBDIRS); do $(MAKE) -C $$x clean || exit 1 ; done
|
||||||
rm -f *.o *.so asterisk
|
rm -f *.o *.so asterisk
|
||||||
|
rm -f build.h
|
||||||
|
|
||||||
datafiles: all
|
datafiles: all
|
||||||
mkdir -p /var/lib/asterisk/sounds/digits
|
mkdir -p /var/lib/asterisk/sounds/digits
|
||||||
for x in sounds/digits/*; do \
|
for x in sounds/digits/*; do \
|
||||||
install $$x /var/lib/asterisk/sounds/digits ; \
|
install $$x /var/lib/asterisk/sounds/digits ; \
|
||||||
done
|
done
|
||||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-*; do \
|
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep*; do \
|
||||||
install $$x /var/lib/asterisk/sounds ; \
|
install $$x /var/lib/asterisk/sounds ; \
|
||||||
done
|
done
|
||||||
install: all datafiles
|
install: all datafiles
|
||||||
mkdir -p $(MODULES_DIR)
|
mkdir -p $(MODULES_DIR)
|
||||||
|
mkdir -p /usr/sbin
|
||||||
|
install -m 755 asterisk /usr/sbin/
|
||||||
for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done
|
for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done
|
||||||
install -d /usr/include/asterisk
|
install -d /usr/include/asterisk
|
||||||
install include/asterisk/*.h /usr/include/asterisk
|
install include/asterisk/*.h /usr/include/asterisk
|
||||||
|
431
asterisk.c
431
asterisk.c
@@ -19,24 +19,218 @@
|
|||||||
#include <asterisk/channel.h>
|
#include <asterisk/channel.h>
|
||||||
#include <asterisk/ulaw.h>
|
#include <asterisk/ulaw.h>
|
||||||
#include <asterisk/callerid.h>
|
#include <asterisk/callerid.h>
|
||||||
|
#include <asterisk/module.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
#include "asterisk.h"
|
#include "asterisk.h"
|
||||||
|
|
||||||
|
#define AST_MAX_CONNECTS 128
|
||||||
|
#define NUM_MSGS 64
|
||||||
|
|
||||||
int option_verbose=0;
|
int option_verbose=0;
|
||||||
int option_debug=0;
|
int option_debug=0;
|
||||||
int option_nofork=0;
|
int option_nofork=0;
|
||||||
int option_quiet=0;
|
int option_quiet=0;
|
||||||
int option_console=0;
|
int option_console=0;
|
||||||
int option_highpriority=0;
|
int option_highpriority=0;
|
||||||
|
int option_remote=0;
|
||||||
|
int option_exec=0;
|
||||||
int fully_booted = 0;
|
int fully_booted = 0;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct console consoles[AST_MAX_CONNECTS];
|
||||||
|
|
||||||
char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
|
char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
|
||||||
|
|
||||||
|
static int fdprint(int fd, char *s)
|
||||||
|
{
|
||||||
|
return write(fd, s, strlen(s) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void network_verboser(char *s, int pos, int replace, int complete)
|
||||||
|
{
|
||||||
|
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)))
|
||||||
|
strncpy(hostname, "<Unknown>", sizeof(hostname));
|
||||||
|
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];
|
||||||
|
res = select(max + 1, &rfds, NULL, NULL, NULL);
|
||||||
|
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));
|
||||||
|
if (res < 1)
|
||||||
|
break;
|
||||||
|
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;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
for(;;) {
|
||||||
|
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) {
|
||||||
|
if (pipe(consoles[x].p)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
unlink(AST_SOCKET);
|
||||||
|
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;
|
||||||
|
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path));
|
||||||
|
res = bind(ast_socket, (struct sockaddr *)&sun, sizeof(sun));
|
||||||
|
if (res) {
|
||||||
|
ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", AST_SOCKET, strerror(errno));
|
||||||
|
close(ast_socket);
|
||||||
|
ast_socket = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
res = listen(ast_socket, 2);
|
||||||
|
if (res < 0) {
|
||||||
|
ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", AST_SOCKET, strerror(errno));
|
||||||
|
close(ast_socket);
|
||||||
|
ast_socket = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ast_register_verbose(network_verboser);
|
||||||
|
pthread_create(<hread, 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;
|
||||||
|
strncpy(sun.sun_path, AST_SOCKET, sizeof(sun.sun_path));
|
||||||
|
res = connect(ast_consock, (struct sockaddr *)&sun, sizeof(sun));
|
||||||
|
if (res) {
|
||||||
|
close(ast_consock);
|
||||||
|
ast_consock = -1;
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void urg_handler(int num)
|
static void urg_handler(int num)
|
||||||
{
|
{
|
||||||
/* Called by soft_hangup to interrupt the select, read, or other
|
/* Called by soft_hangup to interrupt the select, read, or other
|
||||||
@@ -47,6 +241,18 @@ static void urg_handler(int num)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
static void set_title(char *text)
|
static void set_title(char *text)
|
||||||
{
|
{
|
||||||
/* Set an X-term or screen title */
|
/* Set an X-term or screen title */
|
||||||
@@ -86,19 +292,26 @@ static int set_priority(int pri)
|
|||||||
|
|
||||||
static void quit_handler(int num)
|
static void quit_handler(int num)
|
||||||
{
|
{
|
||||||
static pthread_mutex_t quitlock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
char filename[80] = "";
|
char filename[80] = "";
|
||||||
|
if (option_console || option_remote) {
|
||||||
if (getenv("HOME"))
|
if (getenv("HOME"))
|
||||||
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||||
/* Quit only once */
|
if (strlen(filename))
|
||||||
pthread_mutex_lock(&quitlock);
|
write_history(filename);
|
||||||
|
rl_callback_handler_remove();
|
||||||
|
}
|
||||||
/* Called on exit */
|
/* Called on exit */
|
||||||
if (option_verbose)
|
if (option_verbose && option_console)
|
||||||
ast_verbose("Asterisk ending (%d).\n", num);
|
ast_verbose("Asterisk ending (%d).\n", num);
|
||||||
else if (option_debug)
|
else if (option_debug)
|
||||||
ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
|
ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
|
||||||
if (strlen(filename))
|
if (ast_socket > -1)
|
||||||
write_history(filename);
|
close(ast_socket);
|
||||||
|
if (ast_consock > -1)
|
||||||
|
close(ast_consock);
|
||||||
|
if (ast_socket > -1)
|
||||||
|
unlink(AST_SOCKET);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,10 +349,39 @@ static void consolehandler(char *s)
|
|||||||
fprintf(stdout, "\nUse \"quit\" to exit\n");
|
fprintf(stdout, "\nUse \"quit\" to exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char cmd[1024];
|
||||||
|
|
||||||
|
static void remoteconsolehandler(char *s)
|
||||||
|
{
|
||||||
|
/* Called when readline data is available */
|
||||||
|
if (s && strlen(s))
|
||||||
|
add_history(s);
|
||||||
|
/* 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
|
||||||
|
strncpy(cmd, s, sizeof(cmd));
|
||||||
|
if (!strcasecmp(s, "help"))
|
||||||
|
fprintf(stdout, " !<command> Executes a given shell command\n");
|
||||||
|
if (!strcasecmp(s, "quit"))
|
||||||
|
quit_handler(0);
|
||||||
|
} else
|
||||||
|
fprintf(stdout, "\nUse \"quit\" to exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
static char quit_help[] =
|
static char quit_help[] =
|
||||||
"Usage: quit\n"
|
"Usage: quit\n"
|
||||||
" Exits Asterisk.\n";
|
" Exits Asterisk.\n";
|
||||||
|
|
||||||
|
static char shutdown_help[] =
|
||||||
|
"Usage: shutdown\n"
|
||||||
|
" Shuts down a running Asterisk PBX.\n";
|
||||||
|
|
||||||
static int handle_quit(int fd, int argc, char *argv[])
|
static int handle_quit(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc != 1)
|
if (argc != 1)
|
||||||
@@ -150,22 +392,135 @@ static int handle_quit(int fd, int argc, char *argv[])
|
|||||||
|
|
||||||
#define ASTERISK_PROMPT "*CLI> "
|
#define ASTERISK_PROMPT "*CLI> "
|
||||||
|
|
||||||
|
#define ASTERISK_PROMPT2 "%s*CLI> "
|
||||||
|
|
||||||
static struct ast_cli_entry quit = { { "quit", NULL }, handle_quit, "Exit Asterisk", quit_help };
|
static struct ast_cli_entry quit = { { "quit", NULL }, handle_quit, "Exit Asterisk", quit_help };
|
||||||
|
|
||||||
|
static struct ast_cli_entry astshutdown = { { "shutdown", NULL }, handle_quit, "Shut down an Asterisk PBX", shutdown_help };
|
||||||
|
|
||||||
static char *cli_generator(char *text, int state)
|
static char *cli_generator(char *text, int state)
|
||||||
{
|
{
|
||||||
return ast_cli_generator(rl_line_buffer, text, state);
|
return ast_cli_generator(rl_line_buffer, text, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *console_cli_generator(char *text, int state)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
int res;
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "Searching for '%s', %s %d\n", rl_line_buffer, text, state);
|
||||||
|
#endif
|
||||||
|
snprintf(buf, sizeof(buf),"_COMMAND COMPLETE \"%s\" \"%s\" %d", rl_line_buffer, text, state);
|
||||||
|
fdprint(ast_consock, buf);
|
||||||
|
res = read(ast_consock, buf, sizeof(buf));
|
||||||
|
buf[res] = '\0';
|
||||||
|
#if 0
|
||||||
|
printf("res is %d, buf is '%s'\n", res, buf);
|
||||||
|
#endif
|
||||||
|
if (strncmp(buf, "NULL", 4))
|
||||||
|
return strdup(buf);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ast_remotecontrol(char * data)
|
||||||
|
{
|
||||||
|
char buf[80];
|
||||||
|
int res;
|
||||||
|
int max;
|
||||||
|
int lastpos = 0;
|
||||||
|
fd_set rfds;
|
||||||
|
char filename[80] = "";
|
||||||
|
char *hostname;
|
||||||
|
char *cpid;
|
||||||
|
char *version;
|
||||||
|
int pid;
|
||||||
|
char tmp[80];
|
||||||
|
read(ast_consock, buf, sizeof(buf));
|
||||||
|
if (data) {
|
||||||
|
write(ast_consock, data, strlen(data) + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hostname = strtok(buf, "/");
|
||||||
|
cpid = strtok(NULL, "/");
|
||||||
|
version = strtok(NULL, "/");
|
||||||
|
if (!version)
|
||||||
|
version = "<Version Unknown>";
|
||||||
|
strtok(hostname, ".");
|
||||||
|
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);
|
||||||
|
snprintf(tmp, sizeof(tmp), ASTERISK_PROMPT2, hostname);
|
||||||
|
if (getenv("HOME"))
|
||||||
|
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
|
||||||
|
if (strlen(filename))
|
||||||
|
read_history(filename);
|
||||||
|
ast_cli_register(&quit);
|
||||||
|
ast_cli_register(&astshutdown);
|
||||||
|
rl_callback_handler_install(tmp, remoteconsolehandler);
|
||||||
|
rl_completion_entry_function = (Function *)console_cli_generator;
|
||||||
|
for(;;) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(ast_consock, &rfds);
|
||||||
|
FD_SET(STDIN_FILENO, &rfds);
|
||||||
|
max = ast_consock;
|
||||||
|
if (STDIN_FILENO > max)
|
||||||
|
max = STDIN_FILENO;
|
||||||
|
res = select(max + 1, &rfds, NULL, NULL, NULL);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
ast_log(LOG_ERROR, "select failed: %s\n", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (FD_ISSET(STDIN_FILENO, &rfds)) {
|
||||||
|
rl_callback_read_char();
|
||||||
|
if (strlen(cmd)) {
|
||||||
|
res = write(ast_consock, cmd, strlen(cmd) + 1);
|
||||||
|
if (res < 1) {
|
||||||
|
ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strcpy(cmd, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FD_ISSET(ast_consock, &rfds)) {
|
||||||
|
res = read(ast_consock, buf, sizeof(buf));
|
||||||
|
if (res < 1)
|
||||||
|
break;
|
||||||
|
buf[res] = 0;
|
||||||
|
if (!lastpos)
|
||||||
|
write(STDOUT_FILENO, "\r", 2);
|
||||||
|
write(STDOUT_FILENO, buf, res);
|
||||||
|
if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
|
||||||
|
rl_forced_update_display();
|
||||||
|
lastpos = 0;
|
||||||
|
} else {
|
||||||
|
lastpos = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\nDisconnected from Asterisk server\n");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
int res;
|
int res;
|
||||||
|
int pid;
|
||||||
char filename[80] = "";
|
char filename[80] = "";
|
||||||
char hostname[256];
|
char hostname[256];
|
||||||
|
char * xarg = NULL;
|
||||||
|
sigset_t sigs;
|
||||||
|
|
||||||
if (gethostname(hostname, sizeof(hostname)))
|
if (gethostname(hostname, sizeof(hostname)))
|
||||||
strncpy(hostname, "<Unknown>", sizeof(hostname));
|
strncpy(hostname, "<Unknown>", sizeof(hostname));
|
||||||
|
mainpid = getpid();
|
||||||
ast_ulaw_init();
|
ast_ulaw_init();
|
||||||
callerid_init();
|
callerid_init();
|
||||||
if (getenv("HOME"))
|
if (getenv("HOME"))
|
||||||
@@ -176,7 +531,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* Check for options */
|
/* Check for options */
|
||||||
while((c=getopt(argc, argv, "dvqpc")) != EOF) {
|
while((c=getopt(argc, argv, "fdvqprcx:")) != EOF) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'd':
|
case 'd':
|
||||||
option_debug++;
|
option_debug++;
|
||||||
@@ -186,6 +541,13 @@ int main(int argc, char *argv[])
|
|||||||
option_console++;
|
option_console++;
|
||||||
option_nofork++;
|
option_nofork++;
|
||||||
break;
|
break;
|
||||||
|
case 'f':
|
||||||
|
option_nofork++;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
option_remote++;
|
||||||
|
option_nofork++;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
option_highpriority++;
|
option_highpriority++;
|
||||||
break;
|
break;
|
||||||
@@ -196,14 +558,60 @@ int main(int argc, char *argv[])
|
|||||||
case 'q':
|
case 'q':
|
||||||
option_quiet++;
|
option_quiet++;
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
option_exec++;
|
||||||
|
xarg = optarg;
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ast_tryconnect()) {
|
||||||
|
/* One is already running */
|
||||||
|
if (option_remote) {
|
||||||
|
if (option_exec) {
|
||||||
|
ast_remotecontrol(xarg);
|
||||||
|
quit_handler(0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
quit_handler(0);
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", AST_SOCKET);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else if (option_remote || option_exec) {
|
||||||
|
ast_log(LOG_ERROR, "Unable to connect to remote asterisk\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!option_verbose && !option_console && !option_debug) {
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
ast_log(LOG_ERROR, "Unable to fork(): %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (pid)
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
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);
|
ast_register_verbose(console_verboser);
|
||||||
/* Print a welcome message if desired */
|
/* Print a welcome message if desired */
|
||||||
if (option_verbose || option_console) {
|
if (option_verbose || option_console) {
|
||||||
ast_verbose( "Asterisk, Copyright (C) 1999 Mark Spencer\n");
|
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( "Written by Mark Spencer <markster@linux-support.net>\n");
|
||||||
ast_verbose( "=========================================================================\n");
|
ast_verbose( "=========================================================================\n");
|
||||||
}
|
}
|
||||||
@@ -212,7 +620,8 @@ int main(int argc, char *argv[])
|
|||||||
signal(SIGURG, urg_handler);
|
signal(SIGURG, urg_handler);
|
||||||
signal(SIGINT, quit_handler);
|
signal(SIGINT, quit_handler);
|
||||||
signal(SIGTERM, quit_handler);
|
signal(SIGTERM, quit_handler);
|
||||||
signal(SIGHUP, quit_handler);
|
signal(SIGHUP, hup_handler);
|
||||||
|
signal(SIGPIPE, pipe_handler);
|
||||||
if (set_priority(option_highpriority))
|
if (set_priority(option_highpriority))
|
||||||
exit(1);
|
exit(1);
|
||||||
if (init_logger())
|
if (init_logger())
|
||||||
@@ -228,12 +637,14 @@ int main(int argc, char *argv[])
|
|||||||
if (option_verbose || option_console)
|
if (option_verbose || option_console)
|
||||||
ast_verbose( "Asterisk Ready.\n");
|
ast_verbose( "Asterisk Ready.\n");
|
||||||
fully_booted = 1;
|
fully_booted = 1;
|
||||||
|
pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
|
||||||
|
ast_cli_register(&astshutdown);
|
||||||
if (option_console) {
|
if (option_console) {
|
||||||
/* Console stuff now... */
|
/* Console stuff now... */
|
||||||
/* Register our quit function */
|
/* Register our quit function */
|
||||||
char title[256];
|
char title[256];
|
||||||
set_icon("Asterisk");
|
set_icon("Asterisk");
|
||||||
snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, getpid());
|
snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, mainpid);
|
||||||
set_title(title);
|
set_title(title);
|
||||||
ast_cli_register(&quit);
|
ast_cli_register(&quit);
|
||||||
consolethread = pthread_self();
|
consolethread = pthread_self();
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
diff -uNr audiofile-0.1.9.old/libaudiofile/audiofile.c audiofile-0.1.9/libaudiofile/audiofile.c
|
|
||||||
--- audiofile-0.1.9.old/libaudiofile/audiofile.c Fri Jul 23 12:57:56 1999
|
|
||||||
+++ audiofile-0.1.9/libaudiofile/audiofile.c Fri Dec 10 18:43:30 1999
|
|
||||||
@@ -488,6 +488,20 @@
|
|
||||||
return afOpenVirtualFile(af_virtual_file_new_for_file(fp), mode, setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
+AFfilehandle afOpenFD(int fd, const char *mode, AFfilesetup setup)
|
|
||||||
+{
|
|
||||||
+ FILE *fp;
|
|
||||||
+
|
|
||||||
+ fp = fdopen(fd, mode);
|
|
||||||
+ if (fp == NULL)
|
|
||||||
+ {
|
|
||||||
+ _af_error(AF_BAD_OPEN);
|
|
||||||
+ return AF_NULL_FILEHANDLE;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return afOpenVirtualFile(af_virtual_file_new_for_file(fp), mode, setup);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int afGetFileFormat (AFfilehandle file, int *version)
|
|
||||||
{
|
|
||||||
assert(file);
|
|
175
cli.c
175
cli.c
@@ -27,6 +27,11 @@
|
|||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
/* For module directory */
|
/* For module directory */
|
||||||
#include "asterisk.h"
|
#include "asterisk.h"
|
||||||
|
#include "build.h"
|
||||||
|
|
||||||
|
#define VERSION_INFO "Asterisk " ASTERISK_VERSION " built by " BUILD_USER "@" BUILD_HOSTNAME \
|
||||||
|
" on a " BUILD_MACHINE " running " BUILD_OS
|
||||||
|
|
||||||
|
|
||||||
void ast_cli(int fd, char *fmt, ...)
|
void ast_cli(int fd, char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -66,6 +71,21 @@ static char chanlist_help[] =
|
|||||||
" Lists currently defined channels and some information about\n"
|
" Lists currently defined channels and some information about\n"
|
||||||
" them.\n";
|
" them.\n";
|
||||||
|
|
||||||
|
static char reload_help[] =
|
||||||
|
"Usage: reload\n"
|
||||||
|
" Reloads configuration files for all modules which support\n"
|
||||||
|
" reloading.\n";
|
||||||
|
|
||||||
|
static char set_verbose_help[] =
|
||||||
|
"Usage: set verbose <level>\n"
|
||||||
|
" Sets level of verbose messages to be displayed. 0 means\n"
|
||||||
|
" no messages should be displayed.\n";
|
||||||
|
|
||||||
|
static char softhangup_help[] =
|
||||||
|
"Usage: soft hangup <channel>\n"
|
||||||
|
" Request that a channel be hung up. The hangup takes effect\n"
|
||||||
|
" the next time the driver reads or writes from the channel\n";
|
||||||
|
|
||||||
static int handle_load(int fd, int argc, char *argv[])
|
static int handle_load(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
@@ -77,6 +97,32 @@ static int handle_load(int fd, int argc, char *argv[])
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int handle_reload(int fd, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 1)
|
||||||
|
return RESULT_SHOWUSAGE;
|
||||||
|
ast_module_reload();
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_set_verbose(int fd, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
/* Has a hidden 'at least' argument */
|
||||||
|
if ((argc != 3) && (argc != 4))
|
||||||
|
return RESULT_SHOWUSAGE;
|
||||||
|
if ((argc == 4) && strcasecmp(argv[2], "atleast"))
|
||||||
|
return RESULT_SHOWUSAGE;
|
||||||
|
if (argc == 3)
|
||||||
|
option_verbose = atoi(argv[2]);
|
||||||
|
else {
|
||||||
|
val = atoi(argv[3]);
|
||||||
|
if (val > option_verbose)
|
||||||
|
option_verbose = val;
|
||||||
|
}
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_unload(int fd, int argc, char *argv[])
|
static int handle_unload(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
@@ -122,30 +168,41 @@ static char modlist_help[] =
|
|||||||
" Shows Asterisk modules currently in use, and usage "
|
" Shows Asterisk modules currently in use, and usage "
|
||||||
"statistics.\n";
|
"statistics.\n";
|
||||||
|
|
||||||
|
static char version_help[] =
|
||||||
|
"Usage: show version\n"
|
||||||
|
" Shows Asterisk version information.\n ";
|
||||||
|
|
||||||
static int handle_modlist(int fd, int argc, char *argv[])
|
static int handle_modlist(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
return RESULT_SHOWUSAGE;
|
return RESULT_SHOWUSAGE;
|
||||||
pthread_mutex_lock(&climodentrylock);
|
ast_pthread_mutex_lock(&climodentrylock);
|
||||||
climodentryfd = fd;
|
climodentryfd = fd;
|
||||||
ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
|
ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
|
||||||
ast_update_module_list(modlist_modentry);
|
ast_update_module_list(modlist_modentry);
|
||||||
climodentryfd = -1;
|
climodentryfd = -1;
|
||||||
pthread_mutex_unlock(&climodentrylock);
|
ast_pthread_mutex_unlock(&climodentrylock);
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int handle_version(int fd, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2)
|
||||||
|
return RESULT_SHOWUSAGE;
|
||||||
|
ast_cli(fd, VERSION_INFO);
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
static int handle_chanlist(int fd, int argc, char *argv[])
|
static int handle_chanlist(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
#define FORMAT_STRING "%15s (%-10s %-12s %-4d) %-12s %-15s\n"
|
#define FORMAT_STRING "%15s (%-10s %-12s %-4d) %7s %-12s %-15s\n"
|
||||||
#define FORMAT_STRING2 "%15s (%-10s %-12s %-4s) %-12s %-15s\n"
|
#define FORMAT_STRING2 "%15s (%-10s %-12s %-4s) %7s %-12s %-15s\n"
|
||||||
struct ast_channel *c=NULL;
|
struct ast_channel *c=NULL;
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
return RESULT_SHOWUSAGE;
|
return RESULT_SHOWUSAGE;
|
||||||
c = ast_channel_walk(NULL);
|
c = ast_channel_walk(NULL);
|
||||||
ast_cli(fd, FORMAT_STRING2, "Channel", "Context", "Extension", "Pri", "Appl.", "Data");
|
ast_cli(fd, FORMAT_STRING2, "Channel", "Context", "Extension", "Pri", "State", "Appl.", "Data");
|
||||||
while(c) {
|
while(c) {
|
||||||
ast_cli(fd, FORMAT_STRING, c->name, c->context, c->exten, c->priority,
|
ast_cli(fd, FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->state),
|
||||||
c->appl ? c->appl : "(None)", c->data ? ( strlen(c->data) ? c->data : "(Empty)" ): "(None)");
|
c->appl ? c->appl : "(None)", c->data ? ( strlen(c->data) ? c->data : "(Empty)" ): "(None)");
|
||||||
c = ast_channel_walk(c);
|
c = ast_channel_walk(c);
|
||||||
}
|
}
|
||||||
@@ -156,6 +213,52 @@ static char showchan_help[] =
|
|||||||
"Usage: show channel <channel>\n"
|
"Usage: show channel <channel>\n"
|
||||||
" Shows lots of information about the specified channel.\n";
|
" Shows lots of information about the specified channel.\n";
|
||||||
|
|
||||||
|
static char commandcomplete_help[] =
|
||||||
|
"Usage: _command complete \"<line>\" text state\n"
|
||||||
|
" This function is used internally to help with command completion and should.\n"
|
||||||
|
" never be called by the user directly.\n";
|
||||||
|
|
||||||
|
static int handle_softhangup(int fd, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct ast_channel *c=NULL;
|
||||||
|
if (argc != 3)
|
||||||
|
return RESULT_SHOWUSAGE;
|
||||||
|
c = ast_channel_walk(NULL);
|
||||||
|
while(c) {
|
||||||
|
if (!strcasecmp(c->name, argv[2])) {
|
||||||
|
ast_cli(fd, "Requested Hangup on channel '%s'\n", c->name);
|
||||||
|
c->softhangup = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = ast_channel_walk(c);
|
||||||
|
}
|
||||||
|
if (!c)
|
||||||
|
ast_cli(fd, "%s is not a known channel\n", argv[2]);
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *__ast_cli_generator(char *text, char *word, int state, int lock);
|
||||||
|
|
||||||
|
static int handle_commandcomplete(int fd, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
#if 0
|
||||||
|
printf("Search for %d args: '%s', '%s', '%s', '%s'\n", argc, argv[0], argv[1], argv[2], argv[3]);
|
||||||
|
#endif
|
||||||
|
if (argc != 5)
|
||||||
|
return RESULT_SHOWUSAGE;
|
||||||
|
buf = __ast_cli_generator(argv[2], argv[3], atoi(argv[4]), 0);
|
||||||
|
#if 0
|
||||||
|
printf("Search for '%s' %s %d got '%s'\n", argv[2], argv[3], atoi(argv[4]), buf);
|
||||||
|
#endif
|
||||||
|
if (buf) {
|
||||||
|
ast_cli(fd, buf);
|
||||||
|
free(buf);
|
||||||
|
} else
|
||||||
|
ast_cli(fd, "NULL\n");
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_showchan(int fd, int argc, char *argv[])
|
static int handle_showchan(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct ast_channel *c=NULL;
|
struct ast_channel *c=NULL;
|
||||||
@@ -170,12 +273,12 @@ static int handle_showchan(int fd, int argc, char *argv[])
|
|||||||
" Type: %s\n"
|
" Type: %s\n"
|
||||||
" Caller ID: %s\n"
|
" Caller ID: %s\n"
|
||||||
" DNID Digits: %s\n"
|
" DNID Digits: %s\n"
|
||||||
" State: %d\n"
|
" State: %s (%d)\n"
|
||||||
" Rings: %d\n"
|
" Rings: %d\n"
|
||||||
" WriteFormat: %d\n"
|
" WriteFormat: %d\n"
|
||||||
" ReadFormat: %d\n"
|
" ReadFormat: %d\n"
|
||||||
" NativeFormat: %d\n"
|
" NativeFormat: %d\n"
|
||||||
"File Descriptor: %d\n"
|
"1st File Descriptor: %d\n"
|
||||||
" -- PBX --\n"
|
" -- PBX --\n"
|
||||||
" Context: %s\n"
|
" Context: %s\n"
|
||||||
" Extension: %s\n"
|
" Extension: %s\n"
|
||||||
@@ -186,8 +289,8 @@ static int handle_showchan(int fd, int argc, char *argv[])
|
|||||||
" Blocking in: %s\n",
|
" Blocking in: %s\n",
|
||||||
c->name, c->type,
|
c->name, c->type,
|
||||||
(c->callerid ? c->callerid : "(N/A)"),
|
(c->callerid ? c->callerid : "(N/A)"),
|
||||||
(c->dnid ? c->dnid : "(N/A)" ), c->state, c->rings, c->nativeformats, c->writeformat, c->readformat,
|
(c->dnid ? c->dnid : "(N/A)" ), ast_state2str(c->state), c->state, c->rings, c->nativeformats, c->writeformat, c->readformat,
|
||||||
c->fd, c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
|
c->fds[0], c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
|
||||||
( c-> data ? (strlen(c->data) ? c->data : "(Empty)") : "(None)"),
|
( c-> data ? (strlen(c->data) ? c->data : "(Empty)") : "(None)"),
|
||||||
c->stack, (c->blocking ? c->blockproc : "(Not Blocking)"));
|
c->stack, (c->blocking ? c->blockproc : "(Not Blocking)"));
|
||||||
|
|
||||||
@@ -206,8 +309,10 @@ static char *complete_ch(char *line, char *word, int pos, int state)
|
|||||||
int which=0;
|
int which=0;
|
||||||
c = ast_channel_walk(NULL);
|
c = ast_channel_walk(NULL);
|
||||||
while(c) {
|
while(c) {
|
||||||
|
if (!strncasecmp(word, c->name, strlen(word))) {
|
||||||
if (++which > state)
|
if (++which > state)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
c = ast_channel_walk(c);
|
c = ast_channel_walk(c);
|
||||||
}
|
}
|
||||||
return c ? strdup(c->name) : NULL;
|
return c ? strdup(c->name) : NULL;
|
||||||
@@ -223,7 +328,7 @@ static char *complete_fn(char *line, char *word, int pos, int state)
|
|||||||
strncpy(filename, word, sizeof(filename));
|
strncpy(filename, word, sizeof(filename));
|
||||||
else
|
else
|
||||||
snprintf(filename, sizeof(filename), "%s/%s", AST_MODULE_DIR, word);
|
snprintf(filename, sizeof(filename), "%s/%s", AST_MODULE_DIR, word);
|
||||||
c = filename_completion_function(filename, state);
|
c = (char*)filename_completion_function(filename, state);
|
||||||
if (c && word[0] != '/')
|
if (c && word[0] != '/')
|
||||||
c += (strlen(AST_MODULE_DIR) + 1);
|
c += (strlen(AST_MODULE_DIR) + 1);
|
||||||
return c ? strdup(c) : c;
|
return c ? strdup(c) : c;
|
||||||
@@ -234,11 +339,16 @@ static int handle_help(int fd, int argc, char *argv[]);
|
|||||||
static struct ast_cli_entry builtins[] = {
|
static struct ast_cli_entry builtins[] = {
|
||||||
/* Keep alphabetized */
|
/* Keep alphabetized */
|
||||||
{ { "help", NULL }, handle_help, "Display help list, or specific help on a command", help_help },
|
{ { "help", NULL }, handle_help, "Display help list, or specific help on a command", help_help },
|
||||||
|
{ { "_command", "complete", NULL }, handle_commandcomplete, "Command complete", commandcomplete_help },
|
||||||
{ { "load", NULL }, handle_load, "Load a dynamic module by name", load_help, complete_fn },
|
{ { "load", NULL }, handle_load, "Load a dynamic module by name", load_help, complete_fn },
|
||||||
|
{ { "reload", NULL }, handle_reload, "Reload configuration", reload_help },
|
||||||
|
{ { "set", "verbose", NULL }, handle_set_verbose, "Set level of verboseness", set_verbose_help },
|
||||||
{ { "show", "channel", NULL }, handle_showchan, "Display information on a specific channel", showchan_help, complete_ch },
|
{ { "show", "channel", NULL }, handle_showchan, "Display information on a specific channel", showchan_help, complete_ch },
|
||||||
{ { "show", "channels", NULL }, handle_chanlist, "Display information on channels", chanlist_help },
|
{ { "show", "channels", NULL }, handle_chanlist, "Display information on channels", chanlist_help },
|
||||||
{ { "show", "modules", NULL }, handle_modlist, "List modules and info", modlist_help },
|
{ { "show", "modules", NULL }, handle_modlist, "List modules and info", modlist_help },
|
||||||
|
{ { "soft", "hangup", NULL }, handle_softhangup, "Request a hangup on a given channel", softhangup_help, complete_ch },
|
||||||
{ { "unload", NULL }, handle_unload, "Unload a dynamic module by name", unload_help, complete_fn },
|
{ { "unload", NULL }, handle_unload, "Unload a dynamic module by name", unload_help, complete_fn },
|
||||||
|
{ { "version", NULL }, handle_version, "Display version info", version_help },
|
||||||
{ { NULL }, NULL, NULL, NULL }
|
{ { NULL }, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -327,7 +437,7 @@ static char *find_best(char *argv[])
|
|||||||
int ast_cli_unregister(struct ast_cli_entry *e)
|
int ast_cli_unregister(struct ast_cli_entry *e)
|
||||||
{
|
{
|
||||||
struct ast_cli_entry *cur, *l=NULL;
|
struct ast_cli_entry *cur, *l=NULL;
|
||||||
pthread_mutex_lock(&clilock);
|
ast_pthread_mutex_lock(&clilock);
|
||||||
cur = helpers;
|
cur = helpers;
|
||||||
while(cur) {
|
while(cur) {
|
||||||
if (e == cur) {
|
if (e == cur) {
|
||||||
@@ -342,7 +452,7 @@ int ast_cli_unregister(struct ast_cli_entry *e)
|
|||||||
l = cur;
|
l = cur;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&clilock);
|
ast_pthread_mutex_unlock(&clilock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,11 +461,11 @@ int ast_cli_register(struct ast_cli_entry *e)
|
|||||||
struct ast_cli_entry *cur, *l=NULL;
|
struct ast_cli_entry *cur, *l=NULL;
|
||||||
char fulle[80], fulltst[80];
|
char fulle[80], fulltst[80];
|
||||||
static int len;
|
static int len;
|
||||||
pthread_mutex_lock(&clilock);
|
ast_pthread_mutex_lock(&clilock);
|
||||||
join2(fulle, sizeof(fulle), e->cmda);
|
join2(fulle, sizeof(fulle), e->cmda);
|
||||||
if (find_cli(e->cmda, -1)) {
|
if (find_cli(e->cmda, -1)) {
|
||||||
ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
|
ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
|
||||||
pthread_mutex_unlock(&clilock);
|
ast_pthread_mutex_unlock(&clilock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
cur = helpers;
|
cur = helpers;
|
||||||
@@ -384,7 +494,7 @@ int ast_cli_register(struct ast_cli_entry *e)
|
|||||||
helpers = e;
|
helpers = e;
|
||||||
e->next = NULL;
|
e->next = NULL;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&clilock);
|
ast_pthread_mutex_unlock(&clilock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,6 +527,9 @@ static int help_workhorse(int fd, char *match[])
|
|||||||
fullcmd = fullcmd1;
|
fullcmd = fullcmd1;
|
||||||
e1++;
|
e1++;
|
||||||
}
|
}
|
||||||
|
/* Hide commands that start with '_' */
|
||||||
|
if (fullcmd[0] == '_')
|
||||||
|
continue;
|
||||||
if (match) {
|
if (match) {
|
||||||
if (strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
|
if (strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
|
||||||
continue;
|
continue;
|
||||||
@@ -469,6 +582,11 @@ static char *parse_args(char *s, int *max, char *argv[])
|
|||||||
goto normal;
|
goto normal;
|
||||||
else
|
else
|
||||||
quoted = !quoted;
|
quoted = !quoted;
|
||||||
|
if (quoted && whitespace) {
|
||||||
|
/* If we're starting a quote, coming off white space start a new word, too */
|
||||||
|
argv[x++] = cur;
|
||||||
|
whitespace=0;
|
||||||
|
}
|
||||||
escaped = 0;
|
escaped = 0;
|
||||||
break;
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
@@ -514,7 +632,7 @@ normal:
|
|||||||
return dup;
|
return dup;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ast_cli_generator(char *text, char *word, int state)
|
static char *__ast_cli_generator(char *text, char *word, int state, int lock)
|
||||||
{
|
{
|
||||||
char *argv[AST_MAX_ARGS];
|
char *argv[AST_MAX_ARGS];
|
||||||
struct ast_cli_entry *e, *e1, *e2;
|
struct ast_cli_entry *e, *e1, *e2;
|
||||||
@@ -528,7 +646,8 @@ char *ast_cli_generator(char *text, char *word, int state)
|
|||||||
|
|
||||||
if ((dup = parse_args(text, &x, argv))) {
|
if ((dup = parse_args(text, &x, argv))) {
|
||||||
join(matchstr, sizeof(matchstr), argv);
|
join(matchstr, sizeof(matchstr), argv);
|
||||||
pthread_mutex_lock(&clilock);
|
if (lock)
|
||||||
|
ast_pthread_mutex_lock(&clilock);
|
||||||
e1 = builtins;
|
e1 = builtins;
|
||||||
e2 = helpers;
|
e2 = helpers;
|
||||||
while(e1->cmda[0] || e2) {
|
while(e1->cmda[0] || e2) {
|
||||||
@@ -549,7 +668,7 @@ char *ast_cli_generator(char *text, char *word, int state)
|
|||||||
fullcmd = fullcmd1;
|
fullcmd = fullcmd1;
|
||||||
e1++;
|
e1++;
|
||||||
}
|
}
|
||||||
if (!strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
|
if ((fullcmd[0] != '_') && !strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
|
||||||
/* We contain the first part of one or more commands */
|
/* We contain the first part of one or more commands */
|
||||||
matchnum++;
|
matchnum++;
|
||||||
if (matchnum > state) {
|
if (matchnum > state) {
|
||||||
@@ -560,7 +679,8 @@ char *ast_cli_generator(char *text, char *word, int state)
|
|||||||
res = e->cmda[x];
|
res = e->cmda[x];
|
||||||
}
|
}
|
||||||
if (res) {
|
if (res) {
|
||||||
pthread_mutex_unlock(&clilock);
|
if (lock)
|
||||||
|
ast_pthread_mutex_unlock(&clilock);
|
||||||
return res ? strdup(res) : NULL;
|
return res ? strdup(res) : NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -569,17 +689,24 @@ char *ast_cli_generator(char *text, char *word, int state)
|
|||||||
/* We have a command in its entirity within us -- theoretically only one
|
/* We have a command in its entirity within us -- theoretically only one
|
||||||
command can have this occur */
|
command can have this occur */
|
||||||
fullcmd = e->generator(text, word, (strlen(word) ? (x - 1) : (x)), state);
|
fullcmd = e->generator(text, word, (strlen(word) ? (x - 1) : (x)), state);
|
||||||
pthread_mutex_unlock(&clilock);
|
if (lock)
|
||||||
|
ast_pthread_mutex_unlock(&clilock);
|
||||||
return fullcmd;
|
return fullcmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&clilock);
|
if (lock)
|
||||||
|
ast_pthread_mutex_unlock(&clilock);
|
||||||
free(dup);
|
free(dup);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *ast_cli_generator(char *text, char *word, int state)
|
||||||
|
{
|
||||||
|
return __ast_cli_generator(text, word, state, 1);
|
||||||
|
}
|
||||||
|
|
||||||
int ast_cli_command(int fd, char *s)
|
int ast_cli_command(int fd, char *s)
|
||||||
{
|
{
|
||||||
char *argv[AST_MAX_ARGS];
|
char *argv[AST_MAX_ARGS];
|
||||||
@@ -590,7 +717,7 @@ int ast_cli_command(int fd, char *s)
|
|||||||
if ((dup = parse_args(s, &x, argv))) {
|
if ((dup = parse_args(s, &x, argv))) {
|
||||||
/* We need at least one entry, or ignore */
|
/* We need at least one entry, or ignore */
|
||||||
if (x > 0) {
|
if (x > 0) {
|
||||||
pthread_mutex_lock(&clilock);
|
ast_pthread_mutex_lock(&clilock);
|
||||||
e = find_cli(argv, 0);
|
e = find_cli(argv, 0);
|
||||||
if (e) {
|
if (e) {
|
||||||
switch(e->handler(fd, x, argv)) {
|
switch(e->handler(fd, x, argv)) {
|
||||||
@@ -601,7 +728,7 @@ int ast_cli_command(int fd, char *s)
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(argv));
|
ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(argv));
|
||||||
pthread_mutex_unlock(&clilock);
|
ast_pthread_mutex_unlock(&clilock);
|
||||||
}
|
}
|
||||||
free(dup);
|
free(dup);
|
||||||
} else {
|
} else {
|
||||||
|
20
make_build_h
Executable file
20
make_build_h
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
HOSTNAME=`uname -n`
|
||||||
|
KERNEL=`uname -r`
|
||||||
|
MACHINE=`uname -m`
|
||||||
|
OS=`uname -s`
|
||||||
|
USER=`whoami`
|
||||||
|
VERSION=`cat .version`
|
||||||
|
rm -f build.h
|
||||||
|
cat > build.h << END
|
||||||
|
/*
|
||||||
|
* build.h
|
||||||
|
* Automatically generated
|
||||||
|
*/
|
||||||
|
#define BUILD_HOSTNAME "${HOSTNAME}"
|
||||||
|
#define BUILD_KERNEL "${KERNEL}"
|
||||||
|
#define BUILD_MACHINE "${MACHINE}"
|
||||||
|
#define BUILD_OS "${OS}"
|
||||||
|
#define BUILD_VERSION "${VERSION}"
|
||||||
|
#define BUILD_USER "${USER}"
|
||||||
|
END
|
Reference in New Issue
Block a user