Compare commits

..

4 Commits
1.0.6 ... 0.7.1

Author SHA1 Message Date
Kevin P. Fleming
869e8bc579 remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.7.1@7221 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 18:24:39 +00:00
Kevin P. Fleming
8bc24fabfa remove remaining .cvsignore files
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.7.1@7220 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 18:09:49 +00:00
Kevin P. Fleming
d7326592f2 automatic tag renames
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/0.7.1@7201 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-27 17:18:34 +00:00
Admin Commit
7f269f6735 This commit was manufactured by cvs2svn to create tag 'v0-7-1'.
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/v0-7-1@2036 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2004-01-14 09:31:24 +00:00
487 changed files with 21229 additions and 54835 deletions

5
BUGS
View File

@@ -1,8 +1,3 @@
Asterisk 1.0-RC-1 Known Major Bugs
==================================
* Some people still have issues with H.323
* QuickNet driver still not entirely stable
Asterisk Bug Tracking Information
=================================

168
CHANGES
View File

@@ -1,171 +1,3 @@
NOTE: Corrections or additions to the ChangeLog may be submitted
to http://bugs.digium.com. Documentation and formatting
fixes are not listed here. A complete listing of changes
is available through the Asterisk-CVS mailing list hosted
at http://lists.digium.com.
Asterisk 1.0.6
-- chan_iax2:
-- Fixed a bug dealing with a division by zero that could cause a crash
-- chan_sip:
-- Behavior was changed so that when a registration fails due to DNS resolution issues,
a retry will be attempted in 20 seconds.
-- Peer settings were not reset to null values when reloading the configuration file.
Behavior has been changed so that these values are now cleared.
-- 'restrictcid' now properly works on MySQL peers.
-- Only use the default callerid if it has been specified.
-- Asterisk was not sending the same From: line in SIP messages during certain times.
Fixed to make sure it stays the same. This makes some providers happier, to a working state.
-- Certain circumstances involving a blank callerid caused asterisk to segmentation fault.
-- There was a problem incorrectly matching codec availablity when global preferences were
different from that of the user. To fix this, processing of SDP data has been moved
to after determining who the call is coming from.
-- Asterisk would run out of RTP ports while waiting for SUBSCRIBE's to expire even though
an RTP port isn't needed in this case. This has been fixed by releasing the ports early.
-- chan_zap:
-- During a certain scenario when using flash and '#' transfers you would hear the
other person and the music they were hearing. This has been fixed.
-- A fix for a compilation issue with gcc4 was added.
-- chan_modem_bestdata:
-- A fix for a compilation issue with gcc4 was added.
-- format_g729:
-- Treat a 10-byte read as an end of file indication instead of an error. Some G729 encoders
like to put 10-bytes at the end to indicate this.
-- res_features:
-- During certain situations when parking a call, both endpoints would get musiconhold.
This has been fixed so the individual who parked the call will hear the digits and not
musiconhold.
-- app_dial:
-- DIALEDPEERNUMBER is now being set, so if you attempted to use it in the past and failed
it should work now.
-- A callerid change caused many headaches, this has been reversed to the original 1.0 behavior.
-- A crash caused with the combination of the 'g' option and # transfer was fixed.
-- app_voicemail:
-- If two people hit the voicemail system at the same time, and were leaving a message
the second message was overwriting the first. This has been fixed so that each one
is distinct and will not overwrite eachother.
-- cdr_tds:
-- If the server you were using was going down, it had the potential to bring your asterisk
server down with it. Extra stuff has been added so as to bring in more error/connection
checking.
-- cdr_pgsql:
-- This will now attempt to reconnect after a connection problem.
-- IAXY firmware:
-- This has been updated to version 23. It includes a fix for lost registrations.
-- internals
-- Behavior was changed for 'show codec <number>' to make it more intuitive. (kshumard)
-- DNS failures and asterisk do not get along too well, this is not totally the case anymore.
-- Asterisk will now handle DNS failures at startup more gracefully, and won't crash and
burn.
-- Choosing to append to a wave file would render the outputted wave file corrupt. Appending
now works again.
-- If you failed to define certain keys, asterisk had the potential to crash when seeing if you had
used them.
-- Attempting to use such things as ${EXTEN:-1} gave a wrong return value. However, this was never
a documented feature...
Asterisk 1.0.5
-- chan_zap
-- fix a callerid bug introduced in 1.0.4
-- app_queue
-- fix some penalty behavior
Asterisk 1.0.4
-- general
-- fix memory leak evident with extensive use of variables
-- update IAXy firmware to version 22
-- enable some special write protection
-- enable outbound DTMF
-- fix seg fault with incorrect usage of SetVar
-- other minor fixes including typos and doc updates
-- chan_sip
-- fix codecs to not be case sensitive
-- Re-use auth credentials
-- fix MWI when using type=friend
-- fix global NAT option
-- chan_agent / chan_local
-- fix incorrect use count
-- chan_zap
-- Allow CID rings to be configured in zapata.conf
-- no more patching needed for UK CID
-- app_macro
-- allow Macros to exit with '*' or '#' like regular extension processing
-- app_voicemail
-- don't allow '#' as a password
-- add option to save voicemail before going to the operator
-- fix global operator=yes
-- app_read
-- return 0 instead of -1 if user enters nothing
-- res_agi
-- don't exit AGI when file not found to stream
-- send script parameter when using FastAGI
Asterisk 1.0.3
-- chan_zap
-- fix seg fault when doing *0 to flash a trunk
-- rtp
-- seg fault fix
-- chan_sip
-- fix to prevent seg fault when attempting a transfer
-- fix bug with supervised transfers
-- fix codec preferences
-- chan_h323
-- fix compilation problem
-- chan_iax2
-- avoid a deadlock related to a static config of a BUNCH of peers
-- cdr_pgsql
-- fix memory leak when reading config
-- Numerous other minor bug fixes
Asterisk 1.0.2
-- Major bugfix release
Asterisk 1.0.1
-- Added AGI over TCP support
-- Add ability to purge callers from queue if no agents are logged in
-- Fix inband PRI indication detection
-- Fix for MGCP - always request digits if no RTP stream
-- Fixed seg fault for ast_control_streamfile
-- Make pick-up extension configurable via features.conf
-- Numerous other bug fixes
Asterisk 1.0.0
-- Use Q.931 standard cause codes for asterisk cause codes
-- Bug fixes from the bug tracker
Asterisk 1.0-RC2
-- Additional CDR backends
-- Allow muted to reconnect
-- Call parking improvements (including SIP parking support)
-- Added licensed hold music from FreePlayMusic
-- GR-303 and Zap improvements
-- More bug fixes from the bug tracker
-- Improved FreeBSD/OpenBSD/MacOS X support
Asterisk 1.0-RC1
-- Innumerable bug fixes and features from the bug tracker
-- Added Open Settlement Protocol (OSP) support
-- Added Non-facility Associated Signalling (NFAS) Support
-- Added alarm Monitoring support
-- Added new MeetMe options
-- Added GR-303 Support
-- Added trunk groups
-- ADPCM Standardization
-- Numerous bug fixes
-- Add IAX2 Firmware Support
-- Add G.726 support
-- Add ices/icecast support
-- Numerous bug fixes
Asterisk 0.7.2
-- Countless small bug fixes from bug tracker
-- DSP Fixes
-- Fix unloading of Zaptel
-- Pass Caller*ID/ANI properly on call forwarding
-- Add indication for Italy
Asterisk 0.7.1
-- Fixed timed include context's and GotoIfTime
-- Fixed chan_h323 it now gets remote ip properly instead of 127.0.0.1

11
CREDITS
View File

@@ -5,8 +5,6 @@ Asterisk:
Pilosoft, Inc. - for supporting ADSI development in Asterisk
Asterlink, Inc. - for supporting broad Asterisk development
GFS - for supporting ALSA development
Telesthetic - for supporting SIP development
@@ -14,7 +12,6 @@ Telesthetic - for supporting SIP development
Christos Ricudis - for substantial code contributions
Paul Bagyenda, Digital Solutions - for initial Voicetronix driver development
=== WISHLIST CONTRIBUTERS ===
Jeremy McNamara - SpeeX support
Nick Seraphin - RDNIS support
@@ -26,8 +23,6 @@ Wasim - Hangup detect
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
=== MISCELLANEOUS PATCHES ===
Anthony Minessale - Countless big and small fixes, and relentless forward push
anthmct@yahoo.com http://www.asterlink.com
James Golovich - Innumerable contributions
You can find him and asterisk-perl at http://asterisk.gnuinter.net
Andre Bierwirth - Extension hints and status
@@ -58,15 +53,11 @@ Thorsten Lockert - OpenBSD, FreeBSD ports, making MacOS X port run on 10.3,
bugs. tholo@sigmasoft.com
Brian West - ODBC support and Bug Marshaling
William Waites - syslog support, SIP NAT traversal for SIP-UA. ww@styx.org
Rich Murphey - Porting to FreeBSD, NetBSD, OpenBSD, and Darwin.
rich@whiteoaklabs.com http://whiteoaklabs.com
=== OTHER CONTRIBUTIONS ===
John Todd - Monkey sounds and associated teletorture prompt
=== HOLD MUSIC ===
Music provided by www.opsound.org
=== OTHER SOURCE CODE IN ASTERISK ===
I did not implement the codecs in asterisk. Here is the copyright on the

View File

@@ -16,11 +16,11 @@ Zaptel compatible hardware
* Wildcard X100P - Single FXO interface connects to Loopstart phone
line
* Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI
* Wildcard T400P - Quad T1 interface connects to four T1/PRI
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
* Wildcard E400P (obsolete)- Quad E1 interface connects to four E1/PRI
(or PRA) interfaces. Supports PRA/PRI, EuroISDN voice and data.
* Wildcard E400P - Quad E1 interface connects to four E1/PRI (or PRA)
interfaces. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
* Wildcard T100P - Single T1 interface connects to a single T1/PRI
interface. Supports RBS and PRI voice and PPP, FR, and HDLC data.

168
Makefile
View File

@@ -20,31 +20,11 @@ OSARCH=$(shell uname -s)
ifeq (${OSARCH},Linux)
PROC=$(shell uname -m)
ifeq ($(PROC),x86_64)
# You must have GCC 3.4 to use k8, otherwise use athlon
PROC=k8
#PROC=athlon
OPTIONS+=-m64
endif
ifeq ($(PROC),sparc64)
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
#This works for even old (2.96) versions of gcc and provides a small boost either way.
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it.
#So we go lowest common available by gcc and go a step down, still a step up from
#the default as we now have a better instruction set to work with. - Belgarath
PROC=ultrasparc
OPTIONS+=$(shell if $(CC) -mtune=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mtune=$(PROC)"; fi)
OPTIONS+=$(shell if $(CC) -mcpu=v8 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mcpu=v8"; fi)
OPTIONS+=-fomit-frame-pointer
endif
MPG123TARG=linux
endif
ifeq ($(findstring BSD,${OSARCH}),BSD)
else
ifeq (${OSARCH},FreeBSD)
PROC=$(shell uname -m)
endif
endif
# Pentium Pro Optimize
#PROC=i686
@@ -63,18 +43,15 @@ PWD=$(shell pwd)
#K6OPT = -DK6OPT
#Tell gcc to optimize the asterisk's code
OPTIMIZE+=-O6
OPTIMIZE=-O6
#Include debug symbols in the executables (-g) and profiling info (-pg)
DEBUG=-g #-pg
# If you are running a radio application, define RADIO_RELAX so that the DTMF
# will be received more reliably
#OPTIONS += -DRADIO_RELAX
# If you don't have a lot of memory (e.g. embedded Asterisk), uncomment the
# following to reduce the size of certain static buffers
#OPTIONS += -DLOW_MEMORY
# New hangup routines for chan_zap.c
# If this flag is uncommented then you need to have new libpri code in your system
# You can still use the old libpri if you do "cvs update -D "08/03/03" in libpri source code
OPTIONS += -DNEW_PRI_HANGUP
# Optional debugging parameters
DEBUG_THREADS = #-DDEBUG_THREADS #-DDO_CRASH
@@ -121,7 +98,6 @@ ASTCONFPATH=$(ASTETCDIR)/asterisk.conf
ASTBINDIR=$(INSTALL_PREFIX)/usr/bin
ASTSBINDIR=$(INSTALL_PREFIX)/usr/sbin
ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run
ASTMANDIR=$(INSTALL_PREFIX)/usr/share/man
MODULES_DIR=$(ASTLIBDIR)/modules
AGI_DIR=$(ASTVARLIBDIR)/agi-bin
@@ -129,29 +105,12 @@ AGI_DIR=$(ASTVARLIBDIR)/agi-bin
INCLUDE=-Iinclude -I../include
CFLAGS=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DMAKE_VALGRIND_HAPPY
CFLAGS+=$(OPTIMIZE)
ifneq ($(PROC),ultrasparc)
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
endif
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
CFLAGS+=$(shell if [ -f /usr/include/osp/osp.h ]; then echo "-DOSP_SUPPORT -I/usr/include/osp" ; fi)
ifeq (${OSARCH},FreeBSD)
OSVERSION=$(shell make -V OSVERSION -f /usr/share/mk/bsd.port.subdir.mk)
CFLAGS+=$(shell if test ${OSVERSION} -lt 500016 ; then echo "-D_THREAD_SAFE"; fi)
LIBS+=$(shell if test ${OSVERSION} -lt 502102 ; then echo "-lc_r"; else echo "-pthread"; fi)
INCLUDE+=-I/usr/local/include
CFLAGS+=$(shell if [ -d /usr/local/include/spandsp ]; then echo "-I/usr/local/include/spandsp"; fi)
MPG123TARG=freebsd
endif # FreeBSD
ifeq (${OSARCH},NetBSD)
CFLAGS+=-pthread
INCLUDE+=-I/usr/local/include -I/usr/pkg/include
MPG123TARG=netbsd
INCLUDE+=-I/usr/local/include
endif
ifeq (${OSARCH},OpenBSD)
CFLAGS+=-pthread
endif
@@ -160,11 +119,10 @@ endif
#CFLAGS+=-DOLD_DSP_ROUTINES
CFLAGS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi)
CFLAGS+=$(shell if [ -f /usr/local/include/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi)
LIBEDIT=editline/libedit.a
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then if [ -f CVS/Tag ] ; then echo "CVS-`sed 's/^T//g' CVS/Tag`-`date +"%D-%T"`"; else echo "CVS-HEAD-`date +"%D-%T"`"; fi; fi; fi)
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then echo "CVS-`date +"%D-%T"`"; fi; fi)
HTTPDIR=$(shell if [ -d /var/www ]; then echo "/var/www"; else echo "/home/httpd"; fi)
RPMVERSION=$(shell if [ -f .version ]; then sed 's/[-\/:]/_/g' .version; else echo "unknown" ; fi)
CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\"
@@ -189,30 +147,29 @@ SUBDIRS=res channels pbx apps codecs formats agi cdr astman stdtime
ifeq (${OSARCH},Linux)
LIBS=-ldl -lpthread
endif
ifeq (${OSARCH},OpenBSD)
LIBS=-pthread
else
ifeq (${OSARCH},FreeBSD)
LIBS=-pthread
else
endif
endif
LIBS+=-lncurses -lm
ifeq (${OSARCH},Linux)
LIBS+=-lresolv #-lnjamd
endif
ifeq (${OSARCH},Darwin)
ifeq ($(shell uname -r),7.0.0)
LIBS+=-lresolv
endif
ifeq (${OSARCH},FreeBSD)
LIBS+=-lcrypto
endif
ifeq (${OSARCH},NetBSD)
LIBS+=-lpthread -lcrypto -lm -L/usr/local/lib -L/usr/pkg/lib -lncurses
endif
ifeq (${OSARCH},OpenBSD)
LIBS=-lcrypto -lpthread -lm -lncurses
endif
LIBS+=-lssl
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 term.o \
ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
cdr.o tdd.o acl.o rtp.o manager.o asterisk.o ast_expr.o \
dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
utils.o
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o
ifeq (${OSARCH},Darwin)
OBJS+=poll.o dlfcn.o
ASTLINK=-Wl,-dynamic
@@ -234,7 +191,7 @@ _all: all
@echo " + $(MAKE) install +"
@echo " +-------------------------------------------+"
all: depend asterisk subdirs
all: depend asterisk subdirs
editline/config.h:
cd editline && unset CFLAGS LIBS && ./configure ; \
@@ -271,14 +228,6 @@ cli.o: cli.c build.h
asterisk.o: asterisk.c build.h
manpage: asterisk.8.gz
asterisk.8.gz: asterisk.sgml
rm -f asterisk.8
docbook2man asterisk.sgml
mv ./*.8 asterisk.8
gzip asterisk.8
ifneq ($(strip $(ASTERISKVERSION)),)
build.h: .version
./make_build_h
@@ -296,10 +245,7 @@ stdtime/libtime.a: FORCE
fi
asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a $(LIBS)
muted: muted.o
$(CC) -o muted muted.o
$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a
subdirs:
for x in $(SUBDIRS); do $(MAKE) -C $$x || exit 1 ; done
@@ -310,7 +256,6 @@ clean:
rm -f build.h
rm -f ast_expr.c
@if [ -e editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
@if [ -d mpg123-0.59r ]; then $(MAKE) -C mpg123-0.59r clean; fi
$(MAKE) -C db1-ast clean
$(MAKE) -C stdtime clean
@@ -324,25 +269,7 @@ datafiles: all
exit 1; \
fi; \
done
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters
for x in sounds/letters/*.gsm; do \
if grep -q "^%`basename $$x`%" sounds.txt; then \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters ; \
else \
echo "No description for $$x"; \
exit 1; \
fi; \
done
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic
for x in sounds/phonetic/*.gsm; do \
if grep -q "^%`basename $$x`%" sounds.txt; then \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic ; \
else \
echo "No description for $$x"; \
exit 1; \
fi; \
done
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-* sounds/queue-*; do \
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-*; do \
if grep -q "^%`basename $$x`%" sounds.txt; then \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
else \
@@ -360,7 +287,7 @@ datafiles: all
update:
@if [ -d CVS ]; then \
echo "Updating from CVS..." ; \
cvs -q -z3 update -Pd; \
cvs -q update -Pd; \
rm -f .version; \
else \
echo "Not CVS"; \
@@ -374,7 +301,6 @@ bininstall: all
mkdir -p $(DESTDIR)$(ASTSBINDIR)
mkdir -p $(DESTDIR)$(ASTVARRUNDIR)
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/tmp
install -m 755 asterisk $(DESTDIR)$(ASTSBINDIR)/
install -m 755 contrib/scripts/astgenkey $(DESTDIR)$(ASTSBINDIR)/
if [ ! -f $(DESTDIR)$(ASTSBINDIR)/safe_asterisk ]; then \
@@ -392,23 +318,19 @@ bininstall: all
rm -f $(DESTDIR)$(ASTSPOOLDIR)/vm; \
fi
ln -s $(ASTSPOOLDIR)/voicemail/default $(DESTDIR)$(ASTSPOOLDIR)/vm
rm -f $(DESTDIR)$(MODULES_DIR)/chan_ixj.so
rm -f $(DESTDIR)$(MODULES_DIR)/chan_tor.so
rm -f $(DESTDIR)$(MODULES_DIR)/cdr_mysql.so
rm -f $(DESTDIR)$(MODULES_DIR)/cdr_unixodbc.so
rm -f $(DESTDIR)$(MODULES_DIR)/codec_mp3_d.so
rm -f $(DESTDIR)$(MODULES_DIR)/format_mp3.so
rm -f $(DESTDIR)$(MODULES_DIR)/app_voicemail2.so
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds
mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/keys
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax
mkdir -p $(DESTDIR)$(ASTMANDIR)/man8
install -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
install -m 644 keys/freeworlddialup.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
install -m 644 asterisk.8.gz $(DESTDIR)$(ASTMANDIR)/man8
if [ -d contrib/firmware/iax ]; then \
install -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax/iaxy.bin; \
else \
echo "You need to do cvs update -d not just cvs update" ; \
fi
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/vm . )
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/voicemail . )
if [ -f mpg123-0.59r/mpg123 ]; then $(MAKE) -C mpg123-0.59r install; fi
@echo " +---- Asterisk Installation Complete -------+"
@echo " + +"
@echo " + YOU MUST READ THE SECURITY DOCUMENT +"
@@ -470,13 +392,12 @@ samples: all datafiles adsi
for x in sounds/*.mp3; do \
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
done
rm -f $(DESTDIR)$(ASTVARLIBDIR)/mohmp3/sample-hold.mp3
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX
:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \
cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm ; \
done
:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm
:> $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail/default/1234/busy.gsm
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isonphone; do \
cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm ; \
done
@@ -501,6 +422,7 @@ webvmail:
mailbox:
./contrib/scripts/addmailbox
rpm: __rpm
@@ -513,16 +435,10 @@ __rpm: _version
cp -f redhat/asterisk /tmp/asterisk/etc/rc.d/init.d/ ; \
sed "s/^Version:.*/Version: $(RPMVERSION)/g" redhat/asterisk.spec > asterisk.spec ; \
rpmbuild --rcfile /usr/lib/rpm/rpmrc:redhat/rpmrc -bb asterisk.spec
progdocs:
doxygen contrib/asterisk-ng-doxygen
mpg123:
@wget -V >/dev/null || (echo "You need wget" ; false )
[ -f mpg123-0.59r.tar.gz ] || wget http://www.mpg123.de/mpg123/mpg123-0.59r.tar.gz
[ -d mpg123-0.59r ] || tar xfz mpg123-0.59r.tar.gz
$(MAKE) -C mpg123-0.59r $(MPG123TARG)
config:
if [ -d /etc/rc.d/init.d ]; then \
install -m 755 contrib/init.d/rc.redhat.asterisk /etc/rc.d/init.d/asterisk; \
@@ -531,6 +447,7 @@ config:
install -m 755 init.asterisk /etc/init.d/asterisk; \
fi
dont-optimize:
$(MAKE) OPTIMIZE= K6OPT= install
@@ -540,21 +457,6 @@ depend: .depend
for x in $(SUBDIRS); do $(MAKE) -C $$x depend || exit 1 ; done
.depend:
@if ! which mpg123 &>/dev/null ; then \
echo "*** You don't have mpg123 installed. You're going to need ***";\
echo "*** it if you want MusicOnHold ***";\
elif ! mpg123 --longhelp 2>&1 | grep .59r &>/dev/null ; then \
echo "*************************************************************";\
echo "*** You have the WRONG version of mpg123... you need .59r ***";\
echo "*** Use 'make mpg123' to get the right verison ***";\
echo "*************************************************************";\
fi
./mkdep ${CFLAGS} `ls *.c`
FORCE:
%_env:
$(MAKE) -C $(shell echo $@ | sed "s/_env//g") env
env:
env

23
README
View File

@@ -14,17 +14,12 @@ on the project itself, please visit the Asterisk home page at:
http://www.asterisk.org
In addition you'll find lot's of information compiled by the Asterisk
community on this Wiki:
http://www.voip-info.org/wiki-Asterisk
* LICENSING
Asterisk is distributed under GNU General Public License. The GPL also
must apply to all loadable modules as well, except as defined below.
Digium, Inc. (formerly Linux Support Services) retains copyright to all
of the core Asterisk system, and therefore can grant, at its sole discretion,
of the core Asterisk system, and therefore can grant, at its sole discression,
the ability for companies, individuals, or organizations to create proprietary
or Open Source (but non-GPL'd) modules which may be dynamically linked at
runtime with the portions of Asterisk which fall under our copyright
@@ -34,7 +29,7 @@ umbrella, or are distributed under more flexible licenses than GPL.
If you wish to use our code in other GPL programs, don't worry -- there
is no requirement that you provide the same exemption in your GPL'd
products (although if you've written a module for Asterisk we would
strongly encourage you to make the same exemption that we do).
strongly encourage you to make the same excemption that we do).
Specific permission is also granted to OpenSSL and OpenH323 to link to
Asterisk.
@@ -50,12 +45,13 @@ licensing scheme are added to the Asterisk-addons CVS module.
== Linux ==
Currently, the Asterisk Open Source PBX is only known to run on the
Linux OS, although it may be portable to other UNIX-like operating systems
(like FreeBSD) as well.
as well.
* GETTING STARTED
First, be sure you've got supported hardware (but note that you don't need ANY hardware, not even a soundcard) to install and run Asterisk. Supported are:
First, be sure you've got supported hardware. To use Asterisk right now,
you will need one of the following:
* All Wildcard (tm) products from Digium (www.digium.com)
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
@@ -64,9 +60,8 @@ First, be sure you've got supported hardware (but note that you don't need ANY h
* ISDN4Linux compatible ISDN card
* Tormenta Dual T1 card (www.bsdtelephony.com.mx)
Hint: CAPI compatible ISDN cards can be run using the add-on channel chan_capi.
So let's proceed:
Assuming you have one of these (most likely the third) you're ready to
proceed:
1) Run "make"
2) Run "make install"
@@ -76,7 +71,7 @@ the sample PBX, with demonstration extensions, etc. If so, run:
"make samples"
Doing so will overwrite any existing config files you have. If you are lacking a soundcard you won't be able to use the DIAL command on the console, though.
Doing so will overwrite any existing config files you have.
Finally, you can launch Asterisk with:
@@ -148,5 +143,3 @@ you're interested in getting more information.
Welcome to the growing worldwide community of Asterisk users!
Mark Spencer

View File

@@ -1,22 +0,0 @@
About Hold Music
================
These files were obtained from http://opsound.org, where the authors placed them
under the Creative Commons Attribution-Share Alike 2.5 license, a copy of which
may be found at http://creativecommons.org.
Credits
================
macroform-cold_day - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
macroform-robot_dity - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
macroform-the_simplicity - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
manolo_camp-morning_coffee - Manolo Camp
beatbastard@gmx.net - http://ccmixter.org/people/ManoloCamp
reno_project-system - Reno Project
renoproject@hotmail.com - http://www.jamendo.com/en/album/23661

View File

@@ -25,15 +25,15 @@ the "default" context within other private contexts by using:
in the appropriate section. A well designed PBX might look like this:
[longdistance]
exten => _91NXXNXXXXXX,1,Dial(Zap/g2/${EXTEN:1})
exten => _91NXXNXXXXXX,1,Dial,Tor/g2/BYEXTENSION
include => local
[local]
exten => _9NXXNXXX,1,Dial(Zap/g2/${EXTEN:1})
exten => _9NXXNXXX,1,Dial,Tor/g2/BYEXTENSION
include => default
[default]
exten => 6123,Dial(Zap/1)
exten => 6123,Dial,Tor/1
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There

138
acl.c
View File

@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
@@ -21,8 +22,6 @@
#include <asterisk/acl.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
@@ -30,13 +29,15 @@
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
#ifdef __OpenBSD__
#include <fcntl.h>
#include <net/route.h>
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
static ast_mutex_t routeseq_lock = AST_MUTEX_INITIALIZER;
#endif
#define AST_SENSE_DENY 0
#define AST_SENSE_ALLOW 1
struct ast_ha {
/* Host access rule */
@@ -54,7 +55,6 @@ struct my_ifreq {
struct sockaddr_in ifru_addr;
};
/* Free HA structure */
void ast_free_ha(struct ast_ha *ha)
{
struct ast_ha *hal;
@@ -65,52 +65,10 @@ void ast_free_ha(struct ast_ha *ha)
}
}
/* Copy HA structure */
static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
{
memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
to->sense = from->sense;
}
/* Create duplicate of ha structure */
static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
{
struct ast_ha *new_ha = malloc(sizeof(struct ast_ha));
/* Copy from original to new object */
ast_copy_ha(original, new_ha);
return(new_ha);
}
/* Create duplicate HA link list */
/* Used in chan_sip2 templates */
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
{
struct ast_ha *start=original;
struct ast_ha *ret = NULL;
struct ast_ha *link,*prev=NULL;
while(start) {
link = ast_duplicate_ha(start); /* Create copy of this object */
if (prev)
prev->next = link; /* Link previous to this object */
if (!ret)
ret = link; /* Save starting point */
start = start->next; /* Go to next object */
prev = link; /* Save pointer to this object */
}
return (ret); /* Return start of list */
}
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
{
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
char *nm="255.255.255.255";
char *nm;
char tmp[256] = "";
struct ast_ha *prev = NULL;
struct ast_ha *ret;
@@ -161,7 +119,6 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
else
ret = ha;
}
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n",stuff, nm);
return ret;
}
@@ -170,13 +127,6 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
/* Start optimistic */
int res = AST_SENSE_ALLOW;
while(ha) {
char iabuf[INET_ADDRSTRLEN];
char iabuf2[INET_ADDRSTRLEN];
/* DEBUG */
ast_log(LOG_DEBUG,
"##### Testing %s with %s\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
ast_inet_ntoa(iabuf2, sizeof(iabuf2), ha->netaddr));
/* For each rule, if this address and the netmask = the net address
apply the current rule */
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
@@ -189,8 +139,7 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
int ast_get_ip(struct sockaddr_in *sin, char *value)
{
struct hostent *hp;
struct ast_hostent ahp;
hp = ast_gethostbyname(value, &ahp);
hp = gethostbyname(value);
if (hp) {
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
} else {
@@ -200,6 +149,12 @@ int ast_get_ip(struct sockaddr_in *sin, char *value)
return 0;
}
int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
{
return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr )
|| (sin1->sin_port != sin2->sin_port));
}
/* iface is the interface (e.g. eth0); address is the return value */
int ast_lookup_iface(char *iface, struct in_addr *address) {
int mysock, res = 0;
@@ -224,37 +179,36 @@ int ast_lookup_iface(char *iface, struct in_addr *address) {
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
{
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
#ifdef __OpenBSD__
struct sockaddr_in *sin;
struct sockaddr *sa;
struct {
struct rt_msghdr m_rtm;
char m_space[512];
} m_rtmsg;
char iabuf[INET_ADDRSTRLEN];
char *cp, *p;
char *cp, *p = ast_strdupa(inet_ntoa(*them));
int i, l, s, seq, flags;
pid_t pid = getpid();
static int routeseq; /* Protected by "routeseq_lock" mutex */
p = ast_strdupa(ast_inet_ntoa(iabuf, sizeof(iabuf), *them));
memset(us, 0, sizeof(struct in_addr));
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
m_rtmsg.m_rtm.rtm_type = RTM_GET;
m_rtmsg.m_rtm.rtm_flags = RTF_UP | RTF_HOST;
m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
ast_mutex_lock(&routeseq_lock);
seq = ++routeseq;
ast_mutex_unlock(&routeseq_lock);
m_rtmsg.m_rtm.rtm_seq = seq;
m_rtmsg.m_rtm.rtm_addrs = RTA_DST | RTA_IFA;
m_rtmsg.m_rtm.rtm_addrs = RTA_IFA | RTA_DST;
m_rtmsg.m_rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
sin = (struct sockaddr_in *)m_rtmsg.m_space;
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_addr = *them;
if ((s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0) {
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
ast_log(LOG_ERROR, "Error opening routing socket\n");
return -1;
}
@@ -267,7 +221,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
}
do {
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != seq || m_rtmsg.m_rtm.rtm_pid != pid));
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != 1 || m_rtmsg.m_rtm.rtm_pid != pid));
if (l < 0) {
if (errno != EAGAIN)
ast_log(LOG_ERROR, "Error reading from routing socket\n");
@@ -299,7 +253,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
if (i == RTA_IFA && sa->sa_family == AF_INET) {
sin = (struct sockaddr_in *)sa;
*us = sin->sin_addr;
ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, ast_inet_ntoa(iabuf, sizeof(iabuf), *us));
ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, inet_ntoa(*us));
return 0;
}
cp += sa->sa_len > 0 ?
@@ -325,7 +279,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
fgets(line,sizeof(line),PROC);
while (!feof(PROC)) {
char iface[256];
char iface[8];
unsigned int dest, gateway, mask;
int i,fieldnum;
char *fields[40];
@@ -349,21 +303,18 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
i = offset - line;
}
}
if (fieldnum >= 8) {
sscanf(fields[0],"%s",iface);
sscanf(fields[1],"%x",&dest);
sscanf(fields[2],"%x",&gateway);
sscanf(fields[7],"%x",&mask);
sscanf(fields[0],"%s",iface);
sscanf(fields[1],"%x",&dest);
sscanf(fields[2],"%x",&gateway);
sscanf(fields[7],"%x",&mask);
#if 0
{ char iabuf[INET_ADDRSTRLEN];
printf("Addr: %s %08x Dest: %08x Mask: %08x\n", ast_inet_ntoa(iabuf, sizeof(iabuf), *them), remote_ip, dest, mask); }
printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
#endif
/* Looks simple, but here is the magic */
if (((remote_ip & mask) ^ dest) == 0) {
res = ast_lookup_iface(iface,us);
break;
}
/* Looks simple, but here is the magic */
if (((remote_ip & mask) ^ dest) == 0) {
res = ast_lookup_iface(iface,us);
break;
}
}
fclose(PROC);
@@ -378,32 +329,3 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
return 0;
#endif
}
int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
{
char ourhost[256];
struct ast_hostent ahp;
struct hostent *hp;
struct in_addr saddr;
/* just use the bind address if it is nonzero */
if (ntohl(bindaddr.sin_addr.s_addr)) {
memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
return 0;
}
/* try to use our hostname */
if (gethostname(ourhost, sizeof(ourhost))) {
ast_log(LOG_WARNING, "Unable to get hostname\n");
} else {
hp = ast_gethostbyname(ourhost, &ahp);
if (hp) {
memcpy(ourip, hp->h_addr, sizeof(*ourip));
return 0;
}
}
/* A.ROOT-SERVERS.NET. */
if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
return 0;
return -1;
}

View File

@@ -148,19 +148,13 @@
/* PLATFORM SPECIFIC INCLUDES */
#if defined( __OpenBSD__ )
# include <machine/types.h>
#if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
# include <sys/endian.h>
#elif defined( __FreeBSD__ ) || defined( __NetBSD__ )
# include <sys/types.h>
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined(__APPLE__)
#elif defined( BSD ) && ( BSD >= 199103 )
# include <machine/endian.h>
#elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# include <endian.h>
#if !defined(__APPLE__)
# include <byteswap.h>
#endif
#elif defined( linux )
# include <endian.h>
#endif

View File

@@ -22,13 +22,13 @@ install: all
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done
eagi-test: eagi-test.o
$(CC) $(CFLAGS) -o eagi-test eagi-test.o
$(CC) -o eagi-test eagi-test.o
eagi-sphinx-test: eagi-sphinx-test.o
$(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o
$(CC) -o eagi-sphinx-test eagi-sphinx-test.o
clean:
rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
rm -f *.so *.o look .depend
%.so : %.o
$(CC) -shared -Xlinker -x -o $@ $<

View File

@@ -1,94 +0,0 @@
#!/usr/bin/perl
use strict;
use Socket;
use Carp;
use IO::Handle;
my $port = 4573;
$|=1;
# Setup some variables
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
sub checkresult {
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/) {
$res =~ /result=(-?\d+)/;
if (!length($1)) {
print STDERR "FAIL ($res)\n";
$fail++;
} else {
print STDERR "PASS ($1)\n";
$pass++;
}
} else {
print STDERR "FAIL (unexpected result '$res')\n";
$fail++;
}
}
socket(SERVER, PF_INET, SOCK_STREAM, 0);
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
bind(SERVER, sockaddr_in($port, INADDR_ANY)) || die("can't bind\n");
listen(SERVER, SOMAXCONN);
for(;;) {
my $raddr = accept(CLIENT, SERVER);
my ($s, $p) = sockaddr_in($raddr);
CLIENT->autoflush(1);
while(<CLIENT>) {
chomp;
last unless length($_);
if (/^agi_(\w+)\:\s+(.*)$/) {
$AGI{$1} = $2;
}
}
print STDERR "AGI Environment Dump from $s:$p --\n";
foreach my $i (sort keys %AGI) {
print STDERR " -- $i = $AGI{$i}\n";
}
print STDERR "1. Testing 'sendfile'...";
print CLIENT "STREAM FILE beep \"\"\n";
my $result = <CLIENT>;
&checkresult($result);
print STDERR "2. Testing 'sendtext'...";
print CLIENT "SEND TEXT \"hello world\"\n";
my $result = <CLIENT>;
&checkresult($result);
print STDERR "3. Testing 'sendimage'...";
print CLIENT "SEND IMAGE asterisk-image\n";
my $result = <CLIENT>;
&checkresult($result);
print STDERR "4. Testing 'saynumber'...";
print CLIENT "SAY NUMBER 192837465 \"\"\n";
my $result = <CLIENT>;
&checkresult($result);
print STDERR "5. Testing 'waitdtmf'...";
print CLIENT "WAIT FOR DIGIT 1000\n";
my $result = <CLIENT>;
&checkresult($result);
print STDERR "6. Testing 'record'...";
print CLIENT "RECORD FILE testagi gsm 1234 3000\n";
my $result = <CLIENT>;
&checkresult($result);
print STDERR "6a. Testing 'record' playback...";
print CLIENT "STREAM FILE testagi \"\"\n";
my $result = <CLIENT>;
&checkresult($result);
close(CLIENT);
print STDERR "================== Complete ======================\n";
print STDERR "$tests tests completed, $pass passed, $fail failed\n";
print STDERR "==================================================\n";
}

771
app.c
View File

@@ -1,11 +1,11 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Convenient Application Routines
* Channel Management
*
* Copyright (C) 1999-2004, Digium, Inc.
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
@@ -26,21 +27,15 @@
#include <asterisk/dsp.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include "asterisk.h"
#include "astconf.h"
#define MAX_OTHER_FORMATS 10
/* set timeout to 0 for "standard" timeouts. Set timeout to -1 for
"ludicrous time" (essentially never times out) */
int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
{
int res,to,fto;
/* XXX Merge with full version? XXX */
if (maxlen)
s[0] = '\0';
if (prompt) {
res = ast_streamfile(c, prompt, c->language);
if (res < 0)
@@ -158,14 +153,14 @@ int ast_app_has_voicemail(const char *mailbox)
char *context;
int ret;
/* If no mailbox, return immediately */
if (ast_strlen_zero(mailbox))
if (!strlen(mailbox))
return 0;
if (strchr(mailbox, ',')) {
strncpy(tmp, mailbox, sizeof(tmp) - 1);
strncpy(tmp, mailbox, sizeof(tmp));
mb = tmp;
ret = 0;
while((cur = strsep(&mb, ","))) {
if (!ast_strlen_zero(cur)) {
if (strlen(cur)) {
if (ast_app_has_voicemail(cur))
return 1;
}
@@ -207,15 +202,15 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
if (oldmsgs)
*oldmsgs = 0;
/* If no mailbox, return immediately */
if (ast_strlen_zero(mailbox))
if (!strlen(mailbox))
return 0;
if (strchr(mailbox, ',')) {
int tmpnew, tmpold;
strncpy(tmp, mailbox, sizeof(tmp) - 1);
strncpy(tmp, mailbox, sizeof(tmp));
mb = tmp;
ret = 0;
while((cur = strsep(&mb, ", "))) {
if (!ast_strlen_zero(cur)) {
if (strlen(cur)) {
if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
return -1;
else {
@@ -263,749 +258,3 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
}
return 0;
}
int ast_dtmf_stream(struct ast_channel *chan,struct ast_channel *peer,char *digits,int between)
{
char *ptr=NULL;
int res=0;
struct ast_frame f;
if (!between)
between = 100;
if (peer)
res = ast_autoservice_start(peer);
if (!res) {
res = ast_waitfor(chan,100);
if (res > -1) {
for (ptr=digits;*ptr;*ptr++) {
if (*ptr == 'w') {
res = ast_safe_sleep(chan, 500);
if (res)
break;
continue;
}
memset(&f, 0, sizeof(f));
f.frametype = AST_FRAME_DTMF;
f.subclass = *ptr;
f.src = "ast_dtmf_stream";
if (strchr("0123456789*#abcdABCD",*ptr)==NULL) {
ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
} else {
res = ast_write(chan, &f);
if (res)
break;
/* pause between digits */
res = ast_safe_sleep(chan,between);
if (res)
break;
}
}
}
if (peer)
res = ast_autoservice_stop(peer);
}
return res;
}
struct linear_state {
int fd;
int autoclose;
int allowoverride;
int origwfmt;
};
static void linear_release(struct ast_channel *chan, void *params)
{
struct linear_state *ls = params;
if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
}
if (ls->autoclose)
close(ls->fd);
free(params);
}
static int linear_generator(struct ast_channel *chan, void *data, int len, int samples)
{
struct ast_frame f;
short buf[2048 + AST_FRIENDLY_OFFSET / 2];
struct linear_state *ls = data;
int res;
len = samples * 2;
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
}
memset(&f, 0, sizeof(f));
res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
if (res > 0) {
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_SLINEAR;
f.data = buf + AST_FRIENDLY_OFFSET/2;
f.datalen = res;
f.samples = res / 2;
f.offset = AST_FRIENDLY_OFFSET;
ast_write(chan, &f);
if (res == len)
return 0;
}
return -1;
}
static void *linear_alloc(struct ast_channel *chan, void *params)
{
struct linear_state *ls;
/* In this case, params is already malloc'd */
if (params) {
ls = params;
if (ls->allowoverride)
chan->writeinterrupt = 1;
else
chan->writeinterrupt = 0;
ls->origwfmt = chan->writeformat;
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
free(ls);
ls = params = NULL;
}
}
return params;
}
static struct ast_generator linearstream =
{
alloc: linear_alloc,
release: linear_release,
generate: linear_generator,
};
int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
{
struct linear_state *lin;
char tmpf[256] = "";
int res = -1;
int autoclose = 0;
if (fd < 0) {
if (!filename || ast_strlen_zero(filename))
return -1;
autoclose = 1;
if (filename[0] == '/')
strncpy(tmpf, filename, sizeof(tmpf) - 1);
else
snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_VAR_DIR, "sounds", filename);
fd = open(tmpf, O_RDONLY);
if (fd < 0){
ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
return -1;
}
}
lin = malloc(sizeof(struct linear_state));
if (lin) {
memset(lin, 0, sizeof(lin));
lin->fd = fd;
lin->allowoverride = allowoverride;
lin->autoclose = autoclose;
res = ast_activate_generator(chan, &linearstream, lin);
}
return res;
}
int ast_control_streamfile(struct ast_channel *chan, char *file, char *fwd, char *rev, char *stop, char *pause, int skipms)
{
struct timeval started, ended;
long elapsed = 0,last_elapsed =0;
char *breaks=NULL;
char *end=NULL;
int blen=2;
int res=0;
if (stop)
blen += strlen(stop);
if (pause)
blen += strlen(pause);
if (blen > 2) {
breaks = alloca(blen + 1);
breaks[0] = '\0';
strcat(breaks, stop);
strcat(breaks, pause);
}
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (chan)
ast_stopstream(chan);
if (file) {
if ((end = strchr(file,':'))) {
if (!strcasecmp(end, ":end")) {
*end = '\0';
end++;
}
}
}
for (;;) {
gettimeofday(&started,NULL);
if (chan)
ast_stopstream(chan);
res = ast_streamfile(chan, file, chan->language);
if (!res) {
if (end) {
ast_seekstream(chan->stream, 0, SEEK_END);
end=NULL;
}
res = 1;
if (elapsed) {
ast_stream_fastforward(chan->stream, elapsed);
last_elapsed = elapsed - 200;
}
if (res)
res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
else
break;
}
if (res < 1)
break;
if (pause != NULL && strchr(pause, res)) {
gettimeofday(&ended, NULL);
elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
for(;;) {
if (chan)
ast_stopstream(chan);
res = ast_waitfordigit(chan, 1000);
if (res == 0)
continue;
else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
break;
}
if (res == *pause) {
res = 0;
continue;
}
}
if (res == -1)
break;
/* if we get one of our stop chars, return it to the calling function */
if (stop && strchr(stop, res)) {
/* res = 0; */
break;
}
}
if (chan)
ast_stopstream(chan);
return res;
}
int ast_play_and_wait(struct ast_channel *chan, char *fn)
{
int d;
d = ast_streamfile(chan, fn, chan->language);
if (d)
return d;
d = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
return d;
}
static int global_silence_threshold = 128;
static int global_maxsilence = 0;
int ast_play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
{
char d, *fmts;
char comment[256];
int x, fmtcnt=1, res=-1,outmsg=0;
struct ast_frame *f;
struct ast_filestream *others[MAX_OTHER_FORMATS];
char *sfmt[MAX_OTHER_FORMATS];
char *stringp=NULL;
time_t start, end;
struct ast_dsp *sildet=NULL; /* silence detector dsp */
int totalsilence = 0;
int dspsilence = 0;
int gotsilence = 0; /* did we timeout for silence? */
int rfmt=0;
if (silencethreshold < 0)
silencethreshold = global_silence_threshold;
if (maxsilence < 0)
maxsilence = global_maxsilence;
/* barf if no pointer passed to store duration in */
if (duration == NULL) {
ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
return -1;
}
ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
if (playfile) {
d = ast_play_and_wait(chan, playfile);
if (d > -1)
d = ast_streamfile(chan, "beep",chan->language);
if (!d)
d = ast_waitstream(chan,"");
if (d < 0)
return -1;
}
fmts = ast_strdupa(fmt);
stringp=fmts;
strsep(&stringp, "|");
ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
sfmt[0] = ast_strdupa(fmts);
while((fmt = strsep(&stringp, "|"))) {
if (fmtcnt > MAX_OTHER_FORMATS - 1) {
ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
break;
}
sfmt[fmtcnt++] = ast_strdupa(fmt);
}
time(&start);
end=start; /* pre-initialize end to be same as start in case we never get into loop */
for (x=0;x<fmtcnt;x++) {
others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
if (!others[x]) {
break;
}
}
if (path)
ast_unlock_path(path);
if (maxsilence > 0) {
sildet = ast_dsp_new(); /* Create the silence detector */
if (!sildet) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
return -1;
}
ast_dsp_set_threshold(sildet, silencethreshold);
rfmt = chan->readformat;
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
ast_dsp_free(sildet);
return -1;
}
}
if (x == fmtcnt) {
/* Loop forever, writing the packets we read to the writer(s), until
we read a # or get a hangup */
f = NULL;
for(;;) {
res = ast_waitfor(chan, 2000);
if (!res) {
ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
/* Try one more time in case of masq */
res = ast_waitfor(chan, 2000);
if (!res) {
ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
res = -1;
}
}
if (res < 0) {
f = NULL;
break;
}
f = ast_read(chan);
if (!f)
break;
if (f->frametype == AST_FRAME_VOICE) {
/* write each format */
for (x=0;x<fmtcnt;x++) {
res = ast_writestream(others[x], f);
}
/* Silence Detection */
if (maxsilence > 0) {
dspsilence = 0;
ast_dsp_silence(sildet, f, &dspsilence);
if (dspsilence)
totalsilence = dspsilence;
else
totalsilence = 0;
if (totalsilence > maxsilence) {
/* Ended happily with silence */
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
ast_frfree(f);
gotsilence = 1;
outmsg=2;
break;
}
}
/* Exit on any error */
if (res) {
ast_log(LOG_WARNING, "Error writing frame\n");
ast_frfree(f);
break;
}
} else if (f->frametype == AST_FRAME_VIDEO) {
/* Write only once */
ast_writestream(others[0], f);
} else if (f->frametype == AST_FRAME_DTMF) {
if (f->subclass == '#') {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
res = '#';
outmsg = 2;
ast_frfree(f);
break;
}
}
if (f->subclass == '0') {
/* Check for a '0' during message recording also, in case caller wants operator */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
res = '0';
outmsg = 0;
ast_frfree(f);
break;
}
if (maxtime) {
time(&end);
if (maxtime < (end - start)) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
outmsg = 2;
res = 't';
ast_frfree(f);
break;
}
}
ast_frfree(f);
}
if (end == start) time(&end);
if (!f) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
res = -1;
outmsg=1;
}
} else {
ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
}
*duration = end - start;
for (x=0;x<fmtcnt;x++) {
if (!others[x])
break;
if (res > 0) {
if (totalsilence)
ast_stream_rewind(others[x], totalsilence-200);
else
ast_stream_rewind(others[x], 200);
}
ast_truncstream(others[x]);
ast_closestream(others[x]);
}
if (rfmt) {
if (ast_set_read_format(chan, rfmt)) {
ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
}
}
if (outmsg > 1) {
/* Let them know recording is stopped */
if(!ast_streamfile(chan, "auth-thankyou", chan->language))
ast_waitstream(chan, "");
}
if (sildet)
ast_dsp_free(sildet);
return res;
}
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
{
char d = 0, *fmts;
char comment[256];
int x, fmtcnt=1, res=-1,outmsg=0;
struct ast_frame *f;
struct ast_filestream *others[MAX_OTHER_FORMATS];
struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
char *sfmt[MAX_OTHER_FORMATS];
char *stringp=NULL;
time_t start, end;
struct ast_dsp *sildet; /* silence detector dsp */
int totalsilence = 0;
int dspsilence = 0;
int gotsilence = 0; /* did we timeout for silence? */
int rfmt=0;
char prependfile[80];
if (silencethreshold < 0)
silencethreshold = global_silence_threshold;
if (maxsilence < 0)
maxsilence = global_maxsilence;
/* barf if no pointer passed to store duration in */
if (duration == NULL) {
ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
return -1;
}
ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
if (playfile || beep) {
if (!beep)
d = ast_play_and_wait(chan, playfile);
if (d > -1)
d = ast_streamfile(chan, "beep",chan->language);
if (!d)
d = ast_waitstream(chan,"");
if (d < 0)
return -1;
}
strncpy(prependfile, recordfile, sizeof(prependfile) -1);
strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
fmts = ast_strdupa(fmt);
stringp=fmts;
strsep(&stringp, "|");
ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
sfmt[0] = ast_strdupa(fmts);
while((fmt = strsep(&stringp, "|"))) {
if (fmtcnt > MAX_OTHER_FORMATS - 1) {
ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
break;
}
sfmt[fmtcnt++] = ast_strdupa(fmt);
}
time(&start);
end=start; /* pre-initialize end to be same as start in case we never get into loop */
for (x=0;x<fmtcnt;x++) {
others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
if (!others[x]) {
break;
}
}
sildet = ast_dsp_new(); /* Create the silence detector */
if (!sildet) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
return -1;
}
ast_dsp_set_threshold(sildet, silencethreshold);
if (maxsilence > 0) {
rfmt = chan->readformat;
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
return -1;
}
}
if (x == fmtcnt) {
/* Loop forever, writing the packets we read to the writer(s), until
we read a # or get a hangup */
f = NULL;
for(;;) {
res = ast_waitfor(chan, 2000);
if (!res) {
ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
/* Try one more time in case of masq */
res = ast_waitfor(chan, 2000);
if (!res) {
ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
res = -1;
}
}
if (res < 0) {
f = NULL;
break;
}
f = ast_read(chan);
if (!f)
break;
if (f->frametype == AST_FRAME_VOICE) {
/* write each format */
for (x=0;x<fmtcnt;x++) {
if (!others[x])
break;
res = ast_writestream(others[x], f);
}
/* Silence Detection */
if (maxsilence > 0) {
dspsilence = 0;
ast_dsp_silence(sildet, f, &dspsilence);
if (dspsilence)
totalsilence = dspsilence;
else
totalsilence = 0;
if (totalsilence > maxsilence) {
/* Ended happily with silence */
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
ast_frfree(f);
gotsilence = 1;
outmsg=2;
break;
}
}
/* Exit on any error */
if (res) {
ast_log(LOG_WARNING, "Error writing frame\n");
ast_frfree(f);
break;
}
} else if (f->frametype == AST_FRAME_VIDEO) {
/* Write only once */
ast_writestream(others[0], f);
} else if (f->frametype == AST_FRAME_DTMF) {
/* stop recording with any digit */
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
res = 't';
outmsg = 2;
ast_frfree(f);
break;
}
if (maxtime) {
time(&end);
if (maxtime < (end - start)) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
res = 't';
outmsg=2;
ast_frfree(f);
break;
}
}
ast_frfree(f);
}
if (end == start) time(&end);
if (!f) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
res = -1;
outmsg=1;
#if 0
/* delete all the prepend files */
for (x=0;x<fmtcnt;x++) {
if (!others[x])
break;
ast_closestream(others[x]);
ast_filedelete(prependfile, sfmt[x]);
}
#endif
}
} else {
ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]);
}
*duration = end - start;
#if 0
if (outmsg > 1) {
#else
if (outmsg) {
#endif
struct ast_frame *fr;
for (x=0;x<fmtcnt;x++) {
snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
if (!others[x] || !realfiles[x])
break;
if (totalsilence)
ast_stream_rewind(others[x], totalsilence-200);
else
ast_stream_rewind(others[x], 200);
ast_truncstream(others[x]);
/* add the original file too */
while ((fr = ast_readframe(realfiles[x]))) {
ast_writestream(others[x],fr);
}
ast_closestream(others[x]);
ast_closestream(realfiles[x]);
ast_filerename(prependfile, recordfile, sfmt[x]);
#if 0
ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
#endif
ast_filedelete(prependfile, sfmt[x]);
}
}
if (rfmt) {
if (ast_set_read_format(chan, rfmt)) {
ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
}
}
if (outmsg) {
if (outmsg > 1) {
/* Let them know it worked */
ast_streamfile(chan, "auth-thankyou", chan->language);
ast_waitstream(chan, "");
}
}
return res;
}
int ast_lock_path(const char *path)
{
char *s;
char *fs;
int res;
int fd;
time_t start;
s = alloca(strlen(path) + 10);
fs = alloca(strlen(path) + 20);
if (!fs || !s) {
ast_log(LOG_WARNING, "Out of memory!\n");
return -1;
}
snprintf(fs, strlen(path) + 19, "%s/%s-%08x", path, ".lock", rand());
fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) {
fprintf(stderr, "Unable to create lock file: %s\n", strerror(errno));
return -1;
}
close(fd);
snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
time(&start);
while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
usleep(1);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
}
unlink(fs);
ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
return res;
}
int ast_unlock_path(const char *path)
{
char *s;
s = alloca(strlen(path) + 10);
if (!s)
return -1;
snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
return unlink(s);
}

View File

@@ -17,19 +17,15 @@ USE_POSTGRES_VM_INTERFACE=0
#APPS=app_dial.so app_playback.so app_directory.so app_intercom.so app_mp3.so
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\
app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \
app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \
app_zapateller.so app_setcallerid.so app_festival.so \
app_agi.so app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \
app_zapateller.so app_datetime.so app_setcallerid.so app_festival.so \
app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.so \
app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \
app_authenticate.so app_softhangup.so app_lookupblacklist.so \
app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \
app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so \
app_setcdruserfield.so app_random.so app_ices.so app_eval.so \
app_nbscat.so app_sendtext.so app_exec.so app_sms.so \
app_groupcount.so app_txtcidname.so app_controlplayback.so \
app_talkdetect.so app_alarmreceiver.so app_userevent.so app_verbose.so \
app_test.so app_forkcdr.so
app_setcdruserfield.so app_random.so
ifneq (${OSARCH},Darwin)
APPS+=app_intercom.so
@@ -37,11 +33,9 @@ endif
#APPS+=app_sql_postgres.so
#APPS+=app_sql_odbc.so
#APPS+=app_rpt.so
APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
APPS+=$(shell if [ -f /usr/local/include/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
APPS+=$(shell if [ -f /usr/include/osp/osp.h ]; then echo "app_osplookup.so" ; fi)
#APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.so" ; fi)
CFLAGS+=-fPIC
@@ -66,7 +60,12 @@ app_rpt.so : app_rpt.o
install: all
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
app_todd.o: app_todd.c
gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -c -o app_todd.o app_todd.c
app_todd.so: app_todd.o
$(CC) $(SOLINK) -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
app_voicemail.so : app_voicemail.o
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
@@ -89,7 +88,7 @@ app_sql_odbc.so: app_sql_odbc.o
$(CC) $(SOLINK) -o $@ $< -lodbc
look: look.c
$(CC) -pipe -O6 -g look.c -o look -lncurses
gcc -pipe -O6 -g look.c -o look -lncurses
ifneq ($(wildcard .depend),)
include .depend
@@ -99,6 +98,3 @@ depend: .depend
.depend:
../mkdep $(CFLAGS) `ls *.c`
env:
env

View File

@@ -19,8 +19,6 @@
#include <asterisk/module.h>
#include <asterisk/adsi.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
@@ -30,6 +28,8 @@
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include "../asterisk.h"
#include "../astconf.h"
@@ -178,7 +178,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
maxlen = strlen(src) - 1;
memcpy(out, src, maxlen);
((char *)out)[maxlen] = '\0';
} else if (!ast_strlen_zero(src) && (src[0] == '\\')) {
} else if (strlen(src) && (src[0] == '\\')) {
if (!(argtype & ARG_NUMBER))
return -1;
/* Octal value */
@@ -198,7 +198,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
/* Convert */
*((unsigned int *)out) = htonl(*((unsigned int *)out));
}
} else if ((!ast_strlen_zero(src) && isdigit(src[0]))) {
} else if ((strlen(src) && isdigit(src[0]))) {
if (!(argtype & ARG_NUMBER))
return -1;
/* Hex value */
@@ -666,7 +666,7 @@ static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_sc
}
buf[0] = id;
buf[1] = (cmd << 6) | (disp->id & 0x3f);
buf[1] = (cmd << 6) | (disp->id & 0x2f);
buf[2] = ((line & 0x1f) << 3) | (flag & 0x7);
return 3;
}
@@ -695,18 +695,6 @@ static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_sc
return 2;
}
static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
{
char *tok;
tok = get_token(&args, script, lineno);
if (tok)
ast_log(LOG_WARNING, "CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
buf[0] = id;
buf[1] = 0;
return 2;
}
static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
{
char *tok;
@@ -843,7 +831,6 @@ static struct adsi_key_cmd kcmds[] = {
{ "VOICEMODE", 0x93 },
/* Display call buffer 'n' */
/* Clear call buffer 'n' */
{ "CLEARCB1", 0x95, clearcbone },
{ "DIGITCOLLECT", 0x96, digitcollect },
{ "DIGITDIRECT", 0x96, digitdirect },
{ "CLEAR", 0x97 },
@@ -1363,7 +1350,7 @@ static struct adsi_script *compile_script(char *script)
/* Strip comments */
if (c)
*c = '\0';
if (!ast_strlen_zero(buf))
if (strlen(buf))
adsi_process(scr, buf, script, lineno);
}
}
@@ -1448,7 +1435,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
bytes = 0;
/* Start with key definitions */
for (x=0;x<scr->numkeys;x++) {
if (bytes + scr->keys[x].retstrlen > 253) {
if (bytes + scr->keys[x].retstrlen > 254) {
/* Send what we've collected so far */
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
@@ -1472,7 +1459,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
bytes = 0;
/* Continue with the display messages */
for (x=0;x<scr->numdisplays;x++) {
if (bytes + scr->displays[x].datalen > 253) {
if (bytes + scr->displays[x].datalen > 254) {
/* Send what we've collected so far */
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
@@ -1496,7 +1483,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
bytes = 0;
/* Send subroutines */
for (x=0;x<scr->numsubs;x++) {
if (bytes + scr->subs[x].datalen > 253) {
if (bytes + scr->subs[x].datalen > 254) {
/* Send what we've collected so far */
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
@@ -1540,7 +1527,7 @@ static int adsi_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
if (!data || ast_strlen_zero(data))
if (!data || !strlen(data))
data = "asterisk.adsi";
LOCAL_USER_ADD(u);
if (!adsi_available(chan)) {

View File

@@ -3,20 +3,15 @@
*
* Asterisk Gateway Interface
*
* Copyright (C) 1999-2004, Digium, Inc.
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -30,7 +25,6 @@
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
@@ -42,18 +36,33 @@
#include <asterisk/app.h>
#include <asterisk/dsp.h>
#include <asterisk/musiconhold.h>
#include <asterisk/manager.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include <asterisk/agi.h>
#include "../asterisk.h"
#include "../astconf.h"
#include <pthread.h>
#define MAX_ARGS 128
#define MAX_COMMANDS 128
/* Recycle some stuff from the CLI interface */
#define fdprintf agi_debug_cli
#define fdprintf ast_cli
typedef struct agi_state {
int fd; /* FD for general output */
int audio; /* FD for audio output */
int ctrl; /* FD for input control */
} AGI;
typedef struct agi_command {
/* Null terminated list of the words of the command */
char *cmda[AST_MAX_CMD_LEN];
/* Handler for the command (channel, AGI state, # of arguments, argument list).
Returns RESULT_SHOWUSAGE for improper arguments */
int (*handler)(struct ast_channel *chan, AGI *agi, int argc, char *argv[]);
/* Summary of the command (< 60 characters) */
char *summary;
/* Detailed usage information */
char *usage;
} agi_command;
static char *tdesc = "Asterisk Gateway Interface (AGI)";
@@ -61,25 +70,16 @@ static char *app = "AGI";
static char *eapp = "EAGI";
static char *deadapp = "DeadAGI";
static char *synopsis = "Executes an AGI compliant application";
static char *esynopsis = "Executes an EAGI compliant application";
static char *deadsynopsis = "Executes AGI on a hungup channel";
static char *descrip =
" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
"program on a channel. AGI allows Asterisk to launch external programs\n"
" [E]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
"program on a channel. AGI allows Asterisk to launch external programs\n"
"written in any language to control a telephony channel, play audio,\n"
"read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
"and stdout.\n"
"Returns -1 on hangup (except for DeadAGI) or if application requested\n"
" hangup, or 0 on non-hangup exit. \n"
"Using 'EAGI' provides enhanced AGI, with incoming audio available out of band"
"on file descriptor 3\n\n"
"Use the CLI command 'show agi' to list available agi commands\n";
static int agidebug = 0;
"and stdout. Returns -1 on hangup or if application requested hangup, or\n"
"0 on non-hangup exit. Using 'EAGI' provides enhanced AGI, with audio\n"
"available out of band on file descriptor 3\n";
STANDARD_LOCAL_USER;
@@ -88,113 +88,7 @@ LOCAL_USER_DECL;
#define TONE_BLOCK_SIZE 200
/* Max time to connect to an AGI remote host */
#define MAX_AGI_CONNECT 2000
#define AGI_PORT 4573
static void agi_debug_cli(int fd, char *fmt, ...)
{
char *stuff;
int res = 0;
va_list ap;
va_start(ap, fmt);
res = vasprintf(&stuff, fmt, ap);
va_end(ap);
if (res == -1) {
ast_log(LOG_ERROR, "Out of memory\n");
} else {
if (agidebug)
ast_verbose("AGI Tx >> %s", stuff);
ast_carefulwrite(fd, stuff, strlen(stuff), 100);
free(stuff);
}
}
static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int *opid)
{
int s;
int flags;
struct pollfd pfds[1];
char *host;
char *c; int port = AGI_PORT;
char *script = "";
struct sockaddr_in sin;
struct hostent *hp;
struct ast_hostent ahp;
ast_log(LOG_DEBUG, "Blah\n");
host = ast_strdupa(agiurl + 6);
if (!host)
return -1;
/* Strip off any script name */
if ((c = strchr(host, '/'))) {
*c = '\0';
c++;
script = c;
}
if ((c = strchr(host, ':'))) {
*c = '\0';
c++;
port = atoi(c);
}
if (efd) {
ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
return -1;
}
hp = ast_gethostbyname(host, &ahp);
if (!hp) {
ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
return -1;
}
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) {
ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
return -1;
}
flags = fcntl(s, F_GETFL);
if (flags < 0) {
ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
close(s);
return -1;
}
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
close(s);
return -1;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) {
ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
close(s);
return -1;
}
pfds[0].fd = s;
pfds[0].events = POLLOUT;
if (poll(pfds, 1, MAX_AGI_CONNECT) != 1) {
ast_log(LOG_WARNING, "Connect to '%s' failed!\n", agiurl);
close(s);
return -1;
}
if (write(s, "agi_network: yes\n", strlen("agi_network: yes\n")) < 0) {
ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
close(s);
return -1;
}
ast_log(LOG_DEBUG, "Wow, connected!\n");
/* Send the script parameter */
if (!ast_strlen_zero(script))
fdprintf(s, "agi_network_script: %s\n", script);
fds[0] = s;
fds[1] = s;
*opid = -1;
return 0;
}
static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
static int launch_script(char *script, char *args, int *fds, int *efd, int *opid)
{
char tmp[256];
int pid;
@@ -203,10 +97,6 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
int audio[2];
int x;
int res;
if (!strncasecmp(script, "agi://", 6))
return launch_netscript(script, argv, fds, efd, opid);
if (script[0] != '/') {
snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script);
script = tmp;
@@ -262,7 +152,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
for (x=STDERR_FILENO + 2;x<1024;x++)
close(x);
/* Execute script */
execv(script, argv);
execl(script, script, args, (char *)NULL);
/* Can't use ast_log since FD's are closed */
fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno));
exit(1);
@@ -435,7 +325,8 @@ static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char
fs = ast_openstream(chan, argv[2], chan->language);
if(!fs){
fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
return RESULT_SUCCESS;
ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
return RESULT_FAILURE;
}
ast_seekstream(fs, 0, SEEK_END);
max_length = ast_tellstream(fs);
@@ -465,9 +356,6 @@ static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char
return RESULT_FAILURE;
}
/*--- handle_saynumber: Say number in various language syntaxes ---*/
/* Need to add option for gender here as well. Coders wanted */
/* While waiting, we're sending a (char *) NULL. */
static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
{
int res;
@@ -476,7 +364,7 @@ static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *
return RESULT_SHOWUSAGE;
if (sscanf(argv[2], "%i", &num) != 1)
return RESULT_SHOWUSAGE;
res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
res = ast_say_number_full(chan, num, argv[3], chan->language, agi->audio, agi->ctrl);
if (res == 1)
return RESULT_SUCCESS;
fdprintf(agi->fd, "200 result=%d\n", res);
@@ -490,12 +378,10 @@ static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *
{
int res;
int num;
if (argc != 4)
return RESULT_SHOWUSAGE;
if (sscanf(argv[2], "%i", &num) != 1)
return RESULT_SHOWUSAGE;
res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
if (res == 1) /* New command */
return RESULT_SUCCESS;
@@ -506,41 +392,6 @@ static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *
return RESULT_FAILURE;
}
static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
{
int res;
int num;
if (argc != 4)
return RESULT_SHOWUSAGE;
if (sscanf(argv[2], "%i", &num) != 1)
return RESULT_SHOWUSAGE;
res = ast_say_time(chan, num, argv[3], chan->language);
if (res == 1)
return RESULT_SUCCESS;
fdprintf(agi->fd, "200 result=%d\n", res);
if (res >= 0)
return RESULT_SUCCESS;
else
return RESULT_FAILURE;
}
static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
{
int res;
if (argc != 4)
return RESULT_SHOWUSAGE;
res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
if (res == 1) /* New command */
return RESULT_SUCCESS;
fdprintf(agi->fd, "200 result=%d\n", res);
if (res >= 0)
return RESULT_SUCCESS;
else
return RESULT_FAILURE;
}
static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
{
int res;
@@ -557,8 +408,8 @@ static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *ar
return RESULT_SUCCESS;
else if (res == 1)
fdprintf(agi->fd, "200 result=%s (timeout)\n", data);
else if (res < 0 )
fdprintf(agi->fd, "200 result=-1\n");
else if (res < 0 )
fdprintf(agi->fd, "200 result=-1\n");
else
fdprintf(agi->fd, "200 result=%s\n", data);
if (res >= 0)
@@ -674,8 +525,6 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
if (!fs) {
res = -1;
fdprintf(agi->fd, "200 result=%d (writefile)\n", res);
if (sildet)
ast_dsp_free(sildet);
return RESULT_FAILURE;
}
@@ -692,16 +541,12 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
if (res < 0) {
ast_closestream(fs);
fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
if (sildet)
ast_dsp_free(sildet);
return RESULT_FAILURE;
}
f = ast_read(chan);
if (!f) {
fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", 0, sample_offset);
ast_closestream(fs);
if (sildet)
ast_dsp_free(sildet);
return RESULT_FAILURE;
}
switch(f->frametype) {
@@ -712,8 +557,6 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
ast_closestream(fs);
ast_frfree(f);
if (sildet)
ast_dsp_free(sildet);
return RESULT_SUCCESS;
}
break;
@@ -749,7 +592,6 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
if (gotsilence) {
ast_stream_rewind(fs, silence-1000);
ast_truncstream(fs);
sample_offset = ast_tellstream(fs);
}
fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
ast_closestream(fs);
@@ -793,17 +635,15 @@ static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **ar
return RESULT_SUCCESS;
} else if (argc==2) {
/* one argument: look for info on the specified channel */
c = ast_channel_walk_locked(NULL);
c = ast_channel_walk(NULL);
while (c) {
if (strcasecmp(argv[1],c->name)==0) {
/* we have a matching channel */
ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
fdprintf(agi->fd, "200 result=1\n");
ast_mutex_unlock(&c->lock);
ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
fdprintf(agi->fd, "200 result=1\n");
return RESULT_SUCCESS;
}
ast_mutex_unlock(&c->lock);
c = ast_channel_walk_locked(c);
c = ast_channel_walk(c);
}
/* if we get this far no channel name matched the argument given */
fdprintf(agi->fd, "200 result=-1\n");
@@ -842,35 +682,34 @@ static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char
if (argv[2])
ast_set_callerid(chan, argv[2], 0);
fdprintf(agi->fd, "200 result=1\n");
/* strncpy(chan->callerid, argv[2], sizeof(chan->callerid)-1);
*/ fdprintf(agi->fd, "200 result=1\n");
return RESULT_SUCCESS;
}
static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, char **argv)
{
struct ast_channel *c;
if (argc==2) {
/* no argument: supply info on the current channel */
fdprintf(agi->fd, "200 result=%d\n", chan->_state);
return RESULT_SUCCESS;
} else if (argc==3) {
/* one argument: look for info on the specified channel */
c = ast_channel_walk_locked(NULL);
while (c) {
if (strcasecmp(argv[2],c->name)==0) {
fdprintf(agi->fd, "200 result=%d\n", c->_state);
ast_mutex_unlock(&c->lock);
return RESULT_SUCCESS;
}
ast_mutex_unlock(&c->lock);
c = ast_channel_walk_locked(c);
}
/* if we get this far no channel name matched the argument given */
fdprintf(agi->fd, "200 result=-1\n");
return RESULT_SUCCESS;
} else {
return RESULT_SHOWUSAGE;
}
struct ast_channel *c;
if (argc==2) {
/* no argument: supply info on the current channel */
fdprintf(agi->fd, "200 result=%d\n", chan->_state);
return RESULT_SUCCESS;
} else if (argc==3) {
/* one argument: look for info on the specified channel */
c = ast_channel_walk(NULL);
while (c) {
if (strcasecmp(argv[2],c->name)==0) {
fdprintf(agi->fd, "200 result=%d\n", c->_state);
return RESULT_SUCCESS;
}
c = ast_channel_walk(c);
}
/* if we get this far no channel name matched the argument given */
fdprintf(agi->fd, "200 result=-1\n");
return RESULT_SUCCESS;
} else {
return RESULT_SHOWUSAGE;
}
}
static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
@@ -886,10 +725,10 @@ static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char
{
char *tempstr;
if ((tempstr = pbx_builtin_getvar_helper(chan, argv[2])))
fdprintf(agi->fd, "200 result=1 (%s)\n", tempstr);
if ((tempstr = pbx_builtin_getvar_helper(chan, argv[2])) )
fdprintf(agi->fd, "200 result=1 (%s)\n", tempstr);
else
fdprintf(agi->fd, "200 result=0\n");
fdprintf(agi->fd, "200 result=0\n");
return RESULT_SUCCESS;
}
@@ -937,9 +776,9 @@ static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **arg
return RESULT_SHOWUSAGE;
res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
if (res)
fdprintf(agi->fd, "200 result=0\n");
fdprintf(agi->fd, "200 result=0\n");
else
fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
return RESULT_SUCCESS;
}
@@ -951,9 +790,9 @@ static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **arg
return RESULT_SHOWUSAGE;
res = ast_db_put(argv[2], argv[3], argv[4]);
if (res)
fdprintf(agi->fd, "200 result=0\n");
fdprintf(agi->fd, "200 result=0\n");
else
fdprintf(agi->fd, "200 result=1\n");
fdprintf(agi->fd, "200 result=1\n");
return RESULT_SUCCESS;
}
@@ -989,38 +828,6 @@ static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char *
return RESULT_SUCCESS;
}
static char debug_usage[] =
"Usage: agi debug\n"
" Enables dumping of AGI transactions for debugging purposes\n";
static char no_debug_usage[] =
"Usage: agi no debug\n"
" Disables dumping of AGI transactions for debugging purposes\n";
static int agi_do_debug(int fd, int argc, char *argv[])
{
if (argc != 2)
return RESULT_SHOWUSAGE;
agidebug = 1;
ast_cli(fd, "AGI Debugging Enabled\n");
return RESULT_SUCCESS;
}
static int agi_no_debug(int fd, int argc, char *argv[])
{
if (argc != 3)
return RESULT_SHOWUSAGE;
agidebug = 0;
ast_cli(fd, "AGI Debugging Disabled\n");
return RESULT_SUCCESS;
}
static struct ast_cli_entry cli_debug =
{ { "agi", "debug", NULL }, agi_do_debug, "Enable AGI debugging", debug_usage };
static struct ast_cli_entry cli_no_debug =
{ { "agi", "no", "debug", NULL }, agi_no_debug, "Disable AGI debugging", no_debug_usage };
static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[])
{
fdprintf(agi->fd, "200 result=0\n");
@@ -1182,21 +989,6 @@ static char usage_saydigits[] =
" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
" -1 on error/hangup.\n";
static char usage_saytime[] =
" Usage: SAY TIME <time> <escape digits>\n"
" Say a given time, returning early if any of the given DTMF digits are\n"
" received on the channel. <time> is number of seconds elapsed since 00:00:00\n"
" on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
" completes without a digit being pressed, or the ASCII numerical value of the\n"
" digit if one was pressed or -1 on error/hangup.\n";
static char usage_sayphonetic[] =
" Usage: SAY PHONETIC <string> <escape digits>\n"
" Say a given character string with phonetics, returning early if any of the given DTMF digits\n"
" are received on the channel. Returns 0 if playback completes without a digit\n"
" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
" -1 on error/hangup.\n";
static char usage_getdata[] =
" Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
" Stream the given file, and recieve DTMF data. Returns the digits recieved\n"
@@ -1236,7 +1028,7 @@ static char usage_noop[] =
" Usage: NOOP\n"
" Does nothing.\n";
static agi_command commands[MAX_COMMANDS] = {
static agi_command commands[] = {
{ { "answer", NULL }, handle_answer, "Asserts answer", usage_answer },
{ { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit },
{ { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext },
@@ -1246,8 +1038,6 @@ static agi_command commands[MAX_COMMANDS] = {
{ { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage },
{ { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits },
{ { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber },
{ { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic },
{ { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime },
{ { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata },
{ { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
{ { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension },
@@ -1269,18 +1059,15 @@ static agi_command commands[MAX_COMMANDS] = {
{ { "set", "music", NULL }, handle_setmusic, "Enable/Disable Music on hold generator", usage_setmusic }
};
static void join(char *s, size_t len, char *w[])
static void join(char *s, int len, char *w[])
{
int x;
/* Join words into a string */
if (!s) {
return;
}
s[0] = '\0';
strcpy(s, "");
for (x=0;w[x];x++) {
if (x)
strncat(s, " ", len - strlen(s) - 1);
strncat(s, w[x], len - strlen(s) - 1);
strncat(s, " ", len - strlen(s));
strncat(s, w[x], len - strlen(s));
}
}
@@ -1293,7 +1080,6 @@ static int help_workhorse(int fd, char *match[])
if (match)
join(matchstr, sizeof(matchstr), match);
for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
if (!commands[x].cmda[0]) break;
e = &commands[x];
if (e)
join(fullcmd, sizeof(fullcmd), e->cmda);
@@ -1310,42 +1096,12 @@ static int help_workhorse(int fd, char *match[])
return 0;
}
int agi_register(agi_command *agi)
{
int x;
for (x=0;x<MAX_COMMANDS - 1;x++) {
if (commands[x].cmda[0] == agi->cmda[0]) {
ast_log(LOG_WARNING, "Command already registered!\n");
return -1;
}
}
for (x=0;x<MAX_COMMANDS - 1;x++) {
if (!commands[x].cmda[0]) {
commands[x] = *agi;
return 0;
}
}
ast_log(LOG_WARNING, "No more room for new commands!\n");
return -1;
}
void agi_unregister(agi_command *agi)
{
int x;
for (x=0;x<MAX_COMMANDS - 1;x++) {
if (commands[x].cmda[0] == agi->cmda[0]) {
memset(&commands[x], 0, sizeof(agi_command));
}
}
}
static agi_command *find_command(char *cmds[], int exact)
{
int x;
int y;
int match;
for (x=0;x < sizeof(commands) / sizeof(commands[0]);x++) {
if (!commands[x].cmda[0]) break;
/* start optimistic */
match = 1;
for (y=0;match && cmds[y]; y++) {
@@ -1458,10 +1214,6 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
fdprintf(agi->fd, c->usage);
fdprintf(agi->fd, "520 End of proper usage.\n");
break;
case AST_PBX_KEEPALIVE:
/* We've been asked to keep alive, so do so */
return AST_PBX_KEEPALIVE;
break;
case RESULT_FAILURE:
/* They've already given the failure. We've been hung up on so handle this
appropriately */
@@ -1473,7 +1225,7 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
return 0;
}
#define RETRY 3
static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid)
{
struct ast_channel *c;
int outfd;
@@ -1482,22 +1234,19 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
struct ast_frame *f;
char buf[2048];
FILE *readf;
/* how many times we'll retry if ast_waitfor_nandfs will return without either
channel or file descriptor in case select is interrupted by a system call (EINTR) */
//how many times we'll retry if ast_waitfor_nandfs will return without either channel or file descriptor in case select is interrupted by a system call (EINTR)
int retry = RETRY;
if (!(readf = fdopen(agi->ctrl, "r"))) {
ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
if (pid > -1)
kill(pid, SIGHUP);
close(agi->ctrl);
kill(pid, SIGHUP);
return -1;
}
setlinebuf(readf);
setup_env(chan, request, agi->fd, (agi->audio > -1));
for (;;) {
ms = -1;
c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
if (c) {
retry = RETRY;
/* Idle the channel until we get a command */
@@ -1529,11 +1278,10 @@ static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, i
/* get rid of trailing newline, if any */
if (*buf && buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = 0;
if (agidebug)
ast_verbose("AGI Rx << %s\n", buf);
returnstatus |= agi_handle_command(chan, agi, buf);
/* If the handle_command returns -1, we need to stop */
if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
if (returnstatus < 0) {
break;
}
} else {
@@ -1597,7 +1345,6 @@ static int handle_dumpagihtml(int fd, int argc, char *argv[]) {
for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
char *stringp=NULL;
if (!commands[x].cmda[0]) break;
e = &commands[x];
if (e)
join(fullcmd, sizeof(fullcmd), e->cmda);
@@ -1630,47 +1377,52 @@ static int handle_dumpagihtml(int fd, int argc, char *argv[]) {
return RESULT_SUCCESS;
}
static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int dead)
static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced)
{
int res=0;
struct localuser *u;
char *argv[MAX_ARGS];
char buf[2048]="";
char *tmp = (char *)buf;
int argc = 0;
char *args,*ringy;
char tmp[256];
int fds[2];
int efd = -1;
int pid;
char *stringp;
char *stringp=tmp;
AGI agi;
if (!data || ast_strlen_zero(data)) {
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
return -1;
}
strncpy(buf, data, sizeof(buf) - 1);
memset(&agi, 0, sizeof(agi));
while ((stringp = strsep(&tmp, "|"))) {
argv[argc++] = stringp;
}
argv[argc] = NULL;
strncpy(tmp, data, sizeof(tmp)-1);
strsep(&stringp, "|");
args = strsep(&stringp, "|");
ringy = strsep(&stringp,"|");
if (!args)
args = "";
LOCAL_USER_ADD(u);
#if 0
/* Answer if need be */
if (chan->_state != AST_STATE_UP) {
if (ringy) { /* if for ringing first */
/* a little ringy-dingy first */
ast_indicate(chan, AST_CONTROL_RINGING);
sleep(3);
}
if (ast_answer(chan)) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
#endif
res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
res = launch_script(tmp, args, fds, enhanced ? &efd : NULL, &pid);
if (!res) {
agi.fd = fds[1];
agi.ctrl = fds[0];
agi.audio = efd;
res = run_agi(chan, argv[0], &agi, pid, dead);
res = run_agi(chan, tmp, &agi, pid);
close(fds[0]);
close(fds[1]);
if (efd > -1)
close(efd);
@@ -1681,23 +1433,19 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
static int agi_exec(struct ast_channel *chan, void *data)
{
if (chan->_softhangup)
ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
return agi_exec_full(chan, data, 0, 0);
return agi_exec_full(chan, data, 0);
}
static int eagi_exec(struct ast_channel *chan, void *data)
{
int readformat;
int res;
if (chan->_softhangup)
ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
readformat = chan->readformat;
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
return -1;
}
res = agi_exec_full(chan, data, 1, 0);
res = agi_exec_full(chan, data, 1);
if (!res) {
if (ast_set_read_format(chan, readformat)) {
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
@@ -1706,11 +1454,6 @@ static int eagi_exec(struct ast_channel *chan, void *data)
return res;
}
static int deadagi_exec(struct ast_channel *chan, void *data)
{
return agi_exec_full(chan, data, 0, 1);
}
static char showagi_help[] =
"Usage: show agi [topic]\n"
" When called with a topic as an argument, displays usage\n"
@@ -1733,10 +1476,7 @@ int unload_module(void)
STANDARD_HANGUP_LOCALUSERS;
ast_cli_unregister(&showagi);
ast_cli_unregister(&dumpagihtml);
ast_cli_unregister(&cli_debug);
ast_cli_unregister(&cli_no_debug);
ast_unregister_application(eapp);
ast_unregister_application(deadapp);
return ast_unregister_application(app);
}
@@ -1744,10 +1484,7 @@ int load_module(void)
{
ast_cli_register(&showagi);
ast_cli_register(&dumpagihtml);
ast_cli_register(&cli_debug);
ast_cli_register(&cli_no_debug);
ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
ast_register_application(eapp, eagi_exec, esynopsis, descrip);
ast_register_application(eapp, eagi_exec, synopsis, descrip);
return ast_register_application(app, agi_exec, synopsis, descrip);
}

View File

@@ -1,858 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Central Station Alarm receiver for Ademco Contact ID
*
* Copyright (C) 2004 Steve Rodgers
*
* Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
*
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk details. *
*
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
*
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/ulaw.h>
#include <asterisk/options.h>
#include <asterisk/app.h>
#include <asterisk/dsp.h>
#include <asterisk/config.h>
#include <asterisk/localtime.h>
#include <asterisk/callerid.h>
#include <asterisk/astdb.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/time.h>
#define ALMRCV_CONFIG "alarmreceiver.conf"
#define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
struct event_node{
char data[17];
struct event_node *next;
};
typedef struct event_node event_node_t;
static char *tdesc = "Alarm Receiver for Asterisk";
static char *app = "AlarmReceiver";
static char *synopsis = "Provide support for receving alarm reports from a burglar or fire alarm panel";
static char *descrip =
"Alarm receiver application for Asterisk. Only 1 signalling format is supported at this time:\n"
"Ademco Contact ID. This application should be called whenever there is an alarm panel calling in\n"
"to dump its events. The application will handshake with the alarm panel, and receive events,\n"
"validate them, handshake them, and store them until the panel hangs up. Once the panel hangs up,\n"
"the application will run the command line specified by the eventcmd setting in alarmreceiver.conf\n"
"and pipe the events to the standard input of the application. Alarmreceiver.conf also contains settings\n"
"for DTMF timing, and for the loudness of the acknowledgement tones.\n";
/* Config Variables */
static int fdtimeout = 2000;
static int sdtimeout = 200;
static int toneloudness = 4096;
static int log_individual_events = 0;
static char event_spool_dir[128] = {'\0'};
static char event_app[128] = {'\0'};
static char db_family[128] = {'\0'};
static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
/* Misc variables */
static char event_file[14] = "/event-XXXXXX";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/*
* Attempt to access a database variable and increment it,
* provided that the user defined db-family in alarmreceiver.conf
* The alarmreceiver app will write statistics to a few variables
* in this family if it is defined. If the new key doesn't exist in the
* family, then create it and set its value to 1.
*/
static void database_increment( char *key )
{
int res = 0;
unsigned v;
char value[16];
if(!strlen(db_family))
return; /* If not defined, don't do anything */
res = ast_db_get(db_family, key, value, sizeof(value) - 1);
if(res){
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
/* Guess we have to create it */
res = ast_db_put(db_family, key, "1");
return;
}
sscanf(value, "%u", &v);
v++;
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: New value for %s: %u\n", key, v);
snprintf(value, sizeof(value), "%u", v);
res = ast_db_put(db_family, key, value);
if((res)&&(option_verbose >= 4))
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error");
return;
}
/*
* Build a MuLaw data block for a single frequency tone
*/
static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
{
int i;
float val;
for(i = 0; i < len; i++){
val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
data[i] = AST_LIN2MU((int)val);
}
/* wrap back around from 8000 */
if (*x >= 8000) *x = 0;
return;
}
/*
* Send a single tone burst for a specifed duration and frequency.
* Returns 0 if successful
*/
static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
{
int res = 0;
int i = 0;
int x = 0;
struct ast_frame *f, wf;
struct {
unsigned char offset[AST_FRIENDLY_OFFSET];
unsigned char buf[640];
} tone_block;
for(;;)
{
if (ast_waitfor(chan, -1) < 0){
res = -1;
break;
}
f = ast_read(chan);
if (!f){
res = -1;
break;
}
if (f->frametype == AST_FRAME_VOICE) {
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = tone_block.buf;
wf.datalen = f->datalen;
wf.samples = wf.datalen;
make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
i += wf.datalen / 8;
if (i > duration) {
break;
}
if (ast_write(chan, &wf)){
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
res = -1;
break;
}
}
ast_frfree(f);
}
return res;
}
/*
* Return the difference in milliseconds between two timeval structs
*/
static int ms_diff(struct timeval *tv1, struct timeval *tv2){
int ms;
ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
return(ms);
}
/*
* Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
* treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
* digits.
*
* Returns 0 if all digits successfully received.
* Returns 1 if a digit time out occurred
* Returns -1 if the caller hung up or there was a channel error.
*
*/
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
{
int res = 0;
int i = 0;
int r;
struct ast_frame *f;
struct timeval now, lastdigittime;
gettimeofday(&lastdigittime,NULL);
for(;;){
gettimeofday(&now,NULL);
/* if outa time, leave */
if (ms_diff(&now,&lastdigittime) >
((i > 0) ? sdto : fdto)){
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
ast_log(LOG_DEBUG,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
res = 1;
break;
}
if ((r = ast_waitfor(chan, -1) < 0)) {
ast_log(LOG_DEBUG, "Waitfor returned %d\n", r);
continue;
}
f = ast_read(chan);
if (f == NULL){
res = -1;
break;
}
/* If they hung up, leave */
if ((f->frametype == AST_FRAME_CONTROL) &&
(f->subclass == AST_CONTROL_HANGUP)){
ast_frfree(f);
res = -1;
break;
}
/* if not DTMF, just do it again */
if (f->frametype != AST_FRAME_DTMF){
ast_frfree(f);
continue;
}
digit_string[i++] = f->subclass; /* save digit */
ast_frfree(f);
/* If we have all the digits we expect, leave */
if(i >= length)
break;
gettimeofday(&lastdigittime,NULL);
}
digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
return res;
}
/*
* Write the metadata to the log file
*/
static int write_metadata( FILE *logfile, char *signalling_type, struct ast_channel *chan)
{
int res = 0;
time_t t;
struct tm now;
char *cl,*cn;
char workstring[80];
char timestamp[80];
/* Extract the caller ID location */
strncpy(workstring, chan->callerid, sizeof(workstring) - 1);
workstring[sizeof(workstring) - 1] = '\0';
ast_callerid_parse(workstring, &cn, &cl);
if (cl)
ast_shrink_phone_number(cl);
/* Get the current time */
time(&t);
ast_localtime(&t, &now, NULL);
/* Format the time */
strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
res = fprintf(logfile, "\n\n[metadata]\n\n");
if(res >= 0)
res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
if(res >= 0)
res = fprintf(logfile, "CALLINGFROM=%s\n", (!cl) ? "<unknown>" : cl);
if(res >- 0)
res = fprintf(logfile, "CALLERNAME=%s\n", (!cn) ? "<unknown>" : cn);
if(res >= 0)
res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
if(res >= 0)
res = fprintf(logfile, "[events]\n\n");
if(res < 0){
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't write metadata\n");
ast_log(LOG_DEBUG,"AlarmReceiver: can't write metadata\n");
}
else
res = 0;
return res;
}
/*
* Write a single event to the log file
*/
static int write_event( FILE *logfile, event_node_t *event)
{
int res = 0;
if( fprintf(logfile, "%s\n", event->data) < 0)
res = -1;
return res;
}
/*
* If we are configured to log events, do so here.
*
*/
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
{
int res = 0;
char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
int fd;
FILE *logfile;
event_node_t *elp = event;
if(strlen(event_spool_dir)){
/* Make a template */
strncpy(workstring, event_spool_dir, sizeof(workstring) - 1);
strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
/* Make the temporary file */
fd = mkstemp(workstring);
if(fd == -1){
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't make temporary file\n");
ast_log(LOG_DEBUG,"AlarmReceiver: can't make temporary file\n");
res = -1;
}
if(!res){
logfile = fdopen(fd, "w");
if(logfile){
/* Write the file */
res = write_metadata(logfile, signalling_type, chan);
if(!res)
while((!res) && (elp != NULL)){
res = write_event(logfile, elp);
elp = elp->next;
}
if(!res){
if(fflush(logfile) == EOF)
res = -1;
if(!res){
if(fclose(logfile) == EOF)
res = -1;
}
}
}
else
res = -1;
}
}
return res;
}
/*
* This function implements the logic to receive the Ademco contact ID format.
*
* The function will return 0 when the caller hangs up, else a -1 if there was a problem.
*/
static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
{
int i,j;
int res = 0;
int checksum;
char event[17];
event_node_t *enew, *elp;
int got_some_digits = 0;
int events_received = 0;
int ack_retries = 0;
static char digit_map[15] = "0123456789*#ABC";
static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
database_increment("calls-received");
/* Wait for first event */
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for first event from panel\n");
while(res >= 0){
if(got_some_digits == 0){
/* Send ACK tone sequence */
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
res = send_tone_burst(chan, 1400.0, 100, tldn);
if(!res)
res = ast_safe_sleep(chan, 100);
if(!res){
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
res = send_tone_burst(chan, 2300.0, 100, tldn);
}
}
if( res >= 0)
res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
if (res < 0){
if(events_received == 0)
/* Hangup with no events received should be logged in the DB */
database_increment("no-events-received");
else{
if(ack_retries){
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
database_increment("ack-retries");
}
}
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: App exiting...\n");
res = -1;
break;
}
if(res != 0){
/* Didn't get all of the digits */
if(option_verbose >= 2)
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
if(!got_some_digits){
got_some_digits = (strlen(event)) ? 1 : 0;
ack_retries++;
}
continue;
}
got_some_digits = 1;
if(option_verbose >= 2)
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Received Event %s\n", event);
ast_log(LOG_DEBUG, "AlarmReceiver: Received event: %s\n", event);
/* Calculate checksum */
for(j = 0, checksum = 0; j < 16; j++){
for(i = 0 ; i < sizeof(digit_map) ; i++){
if(digit_map[i] == event[j])
break;
}
if(i == 16)
break;
checksum += digit_weights[i];
}
if(i == 16){
if(option_verbose >= 2)
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
continue; /* Bad character */
}
/* Checksum is mod(15) of the total */
checksum = checksum % 15;
if(checksum){
database_increment("checksum-errors");
if(option_verbose >= 2){
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
continue;
}
}
/* Check the message type for correctness */
if(strncmp(event + 4, "18", 2)){
if(strncmp(event + 4, "98", 2)){
database_increment("format-errors");
if(option_verbose >= 2)
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Wrong message type\n");
ast_log(LOG_DEBUG, "AlarmReceiver: Wrong message type\n");
continue;
}
}
events_received++;
/* Queue the Event */
if((enew = malloc(sizeof(event_node_t))) == NULL){
if(option_verbose >= 1)
ast_verbose(VERBOSE_PREFIX_1 "AlarmReceiver: Failed to allocate memory\n");
ast_log(LOG_WARNING, "AlarmReceiver Failed to allocate memory\n");
res = -1;
break;
}
memset(enew, 0, sizeof(event_node_t));
enew->next = NULL;
strncpy(enew->data, event, sizeof(enew->data) - 1);
/*
* Insert event onto end of list
*/
if(*ehead == NULL){
*ehead = enew;
}
else{
for(elp = *ehead; elp->next != NULL; elp = elp->next)
;
elp->next = enew;
}
if(res > 0)
res = 0;
/* Let the user have the option of logging the single event before sending the kissoff tone */
if((res == 0) && (log_individual_events))
res = log_events(chan, ADEMCO_CONTACT_ID, enew);
/* Wait 200 msec before sending kissoff */
if(res == 0)
res = ast_safe_sleep(chan, 200);
/* Send the kissoff tone */
if(res == 0)
res = send_tone_burst(chan, 1400.0, 900, tldn);
}
return res;
}
/*
* This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
* This function will always return 0.
*/
static int alarmreceiver_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
event_node_t *elp, *efree;
char signalling_type[64] = "";
event_node_t *event_head = NULL;
LOCAL_USER_ADD(u);
/* Set write and read formats to ULAW */
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Setting read and write formats to ULAW\n");
if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
return -1;
}
if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
return -1;
}
/* Set default values for this invokation of the application */
strncpy(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type) - 1);
/* Answer the channel if it is not already */
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Answering channel\n");
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
if (res) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
/* Wait for the connection to settle post-answer */
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for connection to stabilize\n");
res = ast_safe_sleep(chan, 1250);
/* Attempt to receive the events */
if(!res){
/* Determine the protocol to receive in advance */
/* Note: Ademco contact is the only one supported at this time */
/* Others may be added later */
if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
else
res = -1;
}
/* Events queued by receiver, write them all out here if so configured */
if((!res) && (log_individual_events == 0)){
res = log_events(chan, signalling_type, event_head);
}
/*
* Do we exec a command line at the end?
*/
if((!res) && (strlen(event_app)) && (event_head)){
ast_log(LOG_DEBUG,"Alarmreceiver: executing: %s\n", event_app);
ast_safe_system(event_app);
}
/*
* Free up the data allocated in our linked list
*/
for(elp = event_head; (elp != NULL);){
efree = elp;
elp = elp->next;
free(efree);
}
LOCAL_USER_REMOVE(u);
return 0;
}
/*
* Load the configuration from the configuration file
*/
static int load_config(void)
{
struct ast_config *cfg;
char *p;
/* Read in the config file */
cfg = ast_load(ALMRCV_CONFIG);
if(!cfg){
if(option_verbose >= 4)
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
}
else{
p = ast_variable_retrieve(cfg, "general", "eventcmd");
if(p){
strncpy(event_app, p, sizeof(event_app) - 1);
event_app[sizeof(event_app) - 1] = '\0';
}
p = ast_variable_retrieve(cfg, "general", "loudness");
if(p){
toneloudness = atoi(p);
if(toneloudness < 100)
toneloudness = 100;
if(toneloudness > 8192)
toneloudness = 8192;
}
p = ast_variable_retrieve(cfg, "general", "fdtimeout");
if(p){
fdtimeout = atoi(p);
if(fdtimeout < 1000)
fdtimeout = 1000;
if(fdtimeout > 10000)
fdtimeout = 10000;
}
p = ast_variable_retrieve(cfg, "general", "sdtimeout");
if(p){
sdtimeout = atoi(p);
if(sdtimeout < 110)
sdtimeout = 110;
if(sdtimeout > 4000)
sdtimeout = 4000;
}
p = ast_variable_retrieve(cfg, "general", "logindividualevents");
if(p){
log_individual_events = ast_true(p);
}
p = ast_variable_retrieve(cfg, "general", "eventspooldir");
if(p){
strncpy(event_spool_dir, p, sizeof(event_spool_dir) - 1);
event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
}
p = ast_variable_retrieve(cfg, "general", "timestampformat");
if(p){
strncpy(time_stamp_format, p, sizeof(time_stamp_format) - 1);
time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
}
p = ast_variable_retrieve(cfg, "general", "db-family");
if(p){
strncpy(db_family, p, sizeof(db_family) - 1);
db_family[sizeof(db_family) - 1] = '\0';
}
ast_destroy(cfg);
}
return 0;
}
/*
* These functions are required to implement an Asterisk App.
*/
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
load_config();
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -18,14 +18,14 @@
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/app.h>
#include <asterisk/astdb.h>
#include <asterisk/utils.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
static char *tdesc = "Authentication Application";
@@ -41,11 +41,7 @@ static char *descrip =
"an optional set of opions may be provided by concatenating any\n"
"of the following letters:\n"
" a - Set account code to the password that is entered\n"
" d - Interpret path as database key, not literal file\n"
" r - Remove database key upon successful entry (valid with 'd' only)\n"
"\n"
"When using a database key, the value associated with the key can be\n"
"anything.\n"
"Returns 0 if the user enters a valid password within three\n"
"tries, or -1 otherwise (or on hangup).\n";
@@ -62,7 +58,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
char passwd[256];
char *opts;
char *prompt;
if (!data || ast_strlen_zero(data)) {
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
return -1;
}
@@ -89,36 +85,24 @@ static int auth_exec(struct ast_channel *chan, void *data)
break;
res = 0;
if (password[0] == '/') {
if (strchr(opts, 'd')) {
char tmp[256];
/* Compare against a database key */
if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
/* It's a good password */
if (strchr(opts, 'r')) {
ast_db_del(password + 1, passwd);
/* Compare against a file */
FILE *f;
f = fopen(password, "r");
if (f) {
char buf[256] = "";
while(!feof(f)) {
fgets(buf, sizeof(buf), f);
if (!feof(f) && strlen(buf)) {
buf[strlen(buf) - 1] = '\0';
if (strlen(buf) && !strcmp(passwd, buf))
break;
}
break;
}
} else {
/* Compare against a file */
FILE *f;
f = fopen(password, "r");
if (f) {
char buf[256] = "";
while(!feof(f)) {
fgets(buf, sizeof(buf), f);
if (!feof(f) && !ast_strlen_zero(buf)) {
buf[strlen(buf) - 1] = '\0';
if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
break;
}
}
fclose(f);
if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
break;
} else
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
}
fclose(f);
if (strlen(buf) && !strcmp(passwd, buf))
break;
} else
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
} else {
/* Compare against a fixed password */
if (!strcmp(passwd, password))

View File

@@ -27,6 +27,8 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#include <pthread.h>
static char *tdesc = "Check if channel is available";
static char *app = "ChanIsAvail";
@@ -36,14 +38,12 @@ static char *synopsis = "Check if channel is available";
static char *descrip =
" ChanIsAvail(Technology/resource[&Technology2/resource2...]): \n"
"Checks is any of the requested channels are available. If none\n"
"of the requested channels are available the new priority will be\n"
"n+101 (unless such a priority does not exist or on error, in which\n"
"case ChanIsAvail will return -1).\n"
"If any of the requested channels are available, the next priority will be n+1,\n"
"the channel variable ${AVAILCHAN} will be set to the name of the available channel\n"
"and the ChanIsAvail app will return 0.\n"
"${AVAILORIGCHAN} is the canonical channel name that was used to create the channel.\n"
"${AVAILSTATUS} is the status code for the channel.\n";
"of the requested channels are available the new priority will\n"
"be n+101 (unless such a priority does not exist, in which case\n"
"ChanIsAvail will return -1. If any of the requested channels\n"
"are available, the next priority will be n+1, the channel variable\n"
"${AVAILCHAN} will be set to the name of the available channel and\n"
"the ChanIsAvail app will return 0.\n";
STANDARD_LOCAL_USER;
@@ -53,7 +53,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
char info[512], tmp[512], *peers, *tech, *number, *rest, *cur;
char info[256], *peers, *tech, *number, *rest, *cur;
struct ast_channel *tempchan;
if (!data) {
@@ -62,7 +62,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
}
LOCAL_USER_ADD(u);
strncpy(info, (char *)data, sizeof(info)-1);
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
peers = info;
if (peers) {
cur = peers;
@@ -76,16 +76,13 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
tech = cur;
number = strchr(tech, '/');
if (!number) {
ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
return -1;
ast_log(LOG_WARNING, "ChanIsAvail argument takes format (Zap/[device])\n");
continue;
}
*number = '\0';
number++;
if ((tempchan = ast_request(tech, chan->nativeformats, number))) {
pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
/* Store the originally used channel too */
snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
ast_hangup(tempchan);
tempchan = NULL;
res = 1;
@@ -97,7 +94,6 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
if (res < 1) {
pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority+=100;
else

View File

@@ -1,143 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Trivial application to control playback a sound file
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/app.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/utils.h>
#include <string.h>
#include <stdlib.h>
static char *tdesc = "Control Playback Application";
static char *app = "ControlPlayback";
static char *synopsis = "Play a file with fast forward and rewind";
static char *descrip =
"ControlPlayback(filename[|skipms[|ffchar[|rewchar[|stopchar[|pausechr]]]]]):\n"
" Plays back a given filename (do not put extension). Options may also\n"
" be included following a pipe symbol. You can use * and # to rewind and\n"
" fast forward the playback specified. If 'stopchar' is added the file will\n"
" terminate playback when 'stopchar' is pressed. Returns -1 if the channel\n"
" was hung up, or if the file does not exist. Returns 0 otherwise.\n\n"
" Example: exten => 1234,1,ControlPlayback(file|4000|*|#|1|0)\n\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int is_on_phonepad(char key)
{
return (key == 35 || key == 42 || (key >= 48 && key <= 57)) ? 1 : 0;
}
static int controlplayback_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int skipms = 0;
struct localuser *u;
char tmp[256];
char *skip = NULL, *fwd = NULL, *rev = NULL, *stop = NULL, *pause = NULL, *file = NULL;
if (!data || ast_strlen_zero((char *)data)) {
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
return -1;
}
strncpy(tmp, (char *)data, sizeof(tmp)-1);
file = tmp;
if ((skip=strchr(tmp,'|'))) {
*skip = '\0';
*skip++;
fwd=strchr(skip,'|');
if (fwd) {
*fwd = '\0';
*fwd++;
rev = strchr(fwd,'|');
if (rev) {
*rev = '\0';
*rev++;
stop = strchr(rev,'|');
if (stop) {
*stop = '\0';
*stop++;
pause = strchr(stop,'|');
if (pause) {
*pause = '\0';
*pause++;
}
}
}
}
}
skipms = skip ? atoi(skip) : 3000;
if (!skipms)
skipms = 3000;
if (!fwd || !is_on_phonepad(*fwd))
fwd = "#";
if (!rev || !is_on_phonepad(*rev))
rev = "*";
if (stop && !is_on_phonepad(*stop))
stop = NULL;
if (pause && !is_on_phonepad(*pause))
pause = NULL;
LOCAL_USER_ADD(u);
res = ast_control_streamfile(chan, file, fwd, rev, stop, pause, skipms);
LOCAL_USER_REMOVE(u);
/* If we stopped on one of our stop keys, return 0 */
if(stop && strchr(stop, res))
res = 0;
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, controlplayback_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -5,7 +5,7 @@
*
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_cut__v003@the-tilghman.com>
* Tilghman Lesher <app_cut__v002@the-tilghman.com>
*
* $Id$
*
@@ -82,14 +82,14 @@ static int cut_exec(struct ast_channel *chan, void *data)
if (args_okay) {
char d, ds[2];
char *tmp = alloca(strlen(varname) + 4);
char varvalue[MAXRESULT], *tmp2=varvalue;
char *tmp2 = alloca(MAXRESULT);
char retstring[MAXRESULT];
memset(retstring, 0, MAXRESULT);
if (tmp) {
if (tmp && tmp2) {
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
memset(varvalue, 0, sizeof(varvalue));
memset(tmp2, 0, sizeof(tmp2));
} else {
ast_log(LOG_ERROR, "Out of memory");
return -1;
@@ -101,7 +101,7 @@ static int cut_exec(struct ast_channel *chan, void *data)
d = '-';
/* String form of the delimiter, for use with strsep(3) */
snprintf(ds, sizeof(ds), "%c", d);
sprintf(ds,"%c",d);
pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);

View File

@@ -23,6 +23,9 @@
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Date and Time";
static char *app = "DateTime";

View File

@@ -20,31 +20,33 @@
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/pbx.h>
#include <asterisk/astdb.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Database access functions for Asterisk extension logic";
static char *g_descrip =
" DBget(varname=family/key): Retrieves a value from the Asterisk\n"
"database and stores it in the given variable. Always returns 0. If the\n"
"requested key is not found, jumps to priority n+101 if available.\n";
" DBget(varname=family/key): Retrieves a value from the Asterisk\n"
"database and stores it in the given variable. Always returns 0. If the\n"
"requested key is not found, jumps to priority n+101 if available.\n";
static char *p_descrip =
" DBput(family/key=value): Stores the given value in the Asterisk\n"
"database. Always returns 0.\n";
" DBput(family/key=value): Stores the given value in the Asterisk\n"
"database. Always returns 0.\n";
static char *d_descrip =
" DBdel(family/key): Deletes a key from the Asterisk database. Always\n"
"returns 0.\n";
" DBdel(family/key): Deletes a key from the Asterisk database. Always\n"
"returns 0.\n";
static char *dt_descrip =
" DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
"database. Always returns 0.\n";
" DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
"database. Always returns 0.\n";
static char *g_app = "DBget";
static char *p_app = "DBput";
@@ -60,196 +62,255 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int deltree_exec (struct ast_channel *chan, void *data)
static int
deltree_exec (struct ast_channel *chan, void *data)
{
int arglen;
char *argv, *family, *keytree;
int arglen;
char *argv, *family, *keytree;
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) { /* Why would this fail? */
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) /* Why would this fail? */
{
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (strchr (argv, '/')) {
{
family = strsep (&argv, "/");
keytree = strsep (&argv, "\0");
if (!family || !keytree)
{
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (!strlen (keytree))
keytree = 0;
}
} else
{
family = argv;
keytree = 0;
}
if (strchr (argv, '/')) {
family = strsep (&argv, "/");
keytree = strsep (&argv, "\0");
if (!family || !keytree) {
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
if (!strlen (keytree))
keytree = 0;
} else {
family = argv;
keytree = 0;
}
if (option_verbose > 2)
{
if (keytree)
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n",
family, keytree);
else
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
}
if (option_verbose > 2) {
if (keytree)
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
else
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
}
if (ast_db_deltree (family, keytree))
{
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBdeltree: Error deleting key from database.\n");
}
if (ast_db_deltree (family, keytree)) {
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
}
return 0;
return 0;
}
static int del_exec (struct ast_channel *chan, void *data)
{
int arglen;
char *argv, *family, *key;
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) { /* Why would this fail? */
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
static int
del_exec (struct ast_channel *chan, void *data)
{
int arglen;
char *argv, *family, *key;
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) /* Why would this fail? */
{
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (strchr (argv, '/'))
{
family = strsep (&argv, "/");
key = strsep (&argv, "\0");
if (!family || !key)
{
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (strchr (argv, '/')) {
family = strsep (&argv, "/");
key = strsep (&argv, "\0");
if (!family || !key) {
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
if (ast_db_del (family, key)) {
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
}
} else {
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBdel: family=%s, key=%s\n", family, key);
if (ast_db_del (family, key))
{
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBdel: Error deleting key from database.\n");
}
return 0;
}
else
{
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
}
return 0;
}
static int put_exec (struct ast_channel *chan, void *data)
static int
put_exec (struct ast_channel *chan, void *data)
{
int arglen;
char *argv, *value, *family, *key;
int arglen;
char *argv, *value, *family, *key;
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) { /* Why would this fail? */
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) /* Why would this fail? */
{
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (strchr (argv, '/') && strchr (argv, '='))
{
family = strsep (&argv, "/");
key = strsep (&argv, "=");
value = strsep (&argv, "\0");
if (!value || !family || !key)
{
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (strchr (argv, '/') && strchr (argv, '=')) {
family = strsep (&argv, "/");
key = strsep (&argv, "=");
value = strsep (&argv, "\0");
if (!value || !family || !key) {
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBput: family=%s, key=%s, value=%s\n", family, key, value);
if (ast_db_put (family, key, value)) {
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBput: Error writing value to database.\n");
}
} else {
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBput: family=%s, key=%s, value=%s\n", family, key,
value);
if (ast_db_put (family, key, value))
{
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBput: Error writing value to database.\n");
}
return 0;
}
else
{
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
}
return 0;
}
static int get_exec (struct ast_channel *chan, void *data)
static int
get_exec (struct ast_channel *chan, void *data)
{
int arglen;
char *argv, *varname, *family, *key;
char dbresult[256];
int arglen;
char *argv, *varname, *family, *key;
char dbresult[256];
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) { /* Why would this fail? */
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
arglen = strlen (data);
argv = alloca (arglen + 1);
if (!argv) /* Why would this fail? */
{
ast_log (LOG_DEBUG, "Memory allocation failed\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (strchr (argv, '=') && strchr (argv, '/'))
{
varname = strsep (&argv, "=");
family = strsep (&argv, "/");
key = strsep (&argv, "\0");
if (!varname || !family || !key)
{
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
memcpy (argv, data, arglen + 1);
if (strchr (argv, '=') && strchr (argv, '/')) {
varname = strsep (&argv, "=");
family = strsep (&argv, "/");
key = strsep (&argv, "\0");
if (!varname || !family || !key) {
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
return 0;
}
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBget: varname=%s, family=%s, key=%s\n", varname, family, key);
if (!ast_db_get (family, key, dbresult, sizeof (dbresult) - 1)) {
pbx_builtin_setvar_helper (chan, varname, dbresult);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBget: set variable %s to %s\n", varname, dbresult);
} else {
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
/* Send the call to n+101 priority, where n is the current priority */
if (ast_exists_extension (chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
}
} else {
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBget: varname=%s, family=%s, key=%s\n", varname,
family, key);
if (!ast_db_get (family, key, dbresult, sizeof (dbresult) - 1))
{
pbx_builtin_setvar_helper (chan, varname, dbresult);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBget: set variable %s to %s\n", varname, dbresult);
}
return 0;
else
{
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3
"DBget: Value not found in database.\n");
/* Send the call to n+101 priority, where n is the current priority */
if (ast_exists_extension
(chan, chan->context, chan->exten, chan->priority + 101,
chan->callerid))
chan->priority += 100;
}
}
else
{
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
}
return 0;
}
int unload_module (void)
int
unload_module (void)
{
int retval;
int retval;
STANDARD_HANGUP_LOCALUSERS;
retval = ast_unregister_application (dt_app);
retval |= ast_unregister_application (d_app);
retval |= ast_unregister_application (p_app);
retval |= ast_unregister_application (g_app);
STANDARD_HANGUP_LOCALUSERS;
retval = ast_unregister_application (dt_app);
retval |= ast_unregister_application (d_app);
retval |= ast_unregister_application (p_app);
retval |= ast_unregister_application (g_app);
return retval;
return retval;
}
int load_module (void)
int
load_module (void)
{
int retval;
int retval;
retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip);
if (!retval)
retval = ast_register_application (p_app, put_exec, p_synopsis, p_descrip);
if (!retval)
retval = ast_register_application (d_app, del_exec, d_synopsis, d_descrip);
if (!retval)
retval = ast_register_application (dt_app, deltree_exec, dt_synopsis, dt_descrip);
return retval;
retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip);
if (!retval)
retval =
ast_register_application (p_app, put_exec, p_synopsis, p_descrip);
if (!retval)
retval =
ast_register_application (d_app, del_exec, d_synopsis, d_descrip);
if (!retval)
retval =
ast_register_application (dt_app, deltree_exec, dt_synopsis,
dt_descrip);
return retval;
}
char *description (void)
char *
description (void)
{
return tdesc;
return tdesc;
}
int usecount (void)
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
int res;
STANDARD_USECOUNT (res);
return res;
}
char *key ()
char *
key ()
{
return ASTERISK_GPL_KEY;
return ASTERISK_GPL_KEY;
}

View File

@@ -3,9 +3,9 @@
*
* Trivial application to dial a channel and send an URL on answer
*
* Copyright (C) 1999-2004, Digium, Inc.
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -20,12 +20,9 @@
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/say.h>
#include <asterisk/config.h>
#include <asterisk/features.h>
#include <asterisk/parking.h>
#include <asterisk/musiconhold.h>
#include <asterisk/callerid.h>
#include <asterisk/utils.h>
#include <asterisk/app.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
@@ -36,6 +33,8 @@
#include <sys/signal.h>
#include <netinet/in.h>
#include <pthread.h>
static char *tdesc = "Dialing Application";
static char *app = "Dial";
@@ -50,54 +49,28 @@ static char *descrip =
"which first answered. All other calls placed by the Dial app will be hung up\n"
"If a timeout is not specified, the Dial application will wait indefinitely\n"
"until either one of the called channels answers, the user hangs up, or all\n"
"channels return busy or error. In general, the dialer will return 0 if it\n"
"channels return busy or error. In general, the dialler will return 0 if it\n"
"was unable to place the call, or the timeout expired. However, if all\n"
"channels were busy, and there exists an extension with priority n+101 (where\n"
"n is the priority of the dialer instance), then it will be the next\n"
"n is the priority of the dialler instance), then it will be the next\n"
"executed extension (this allows you to setup different behavior on busy from\n"
"no-answer).\n"
" This application returns -1 if the originating channel hangs up, or if the\n"
"call is bridged and either of the parties in the bridge terminate the call.\n"
"The option string may contain zero or more of the following characters:\n"
" 't' -- allow the called user transfer the calling user by hitting #.\n"
" 'T' -- allow the calling user to transfer the call by hitting #.\n"
" 'f' -- Forces callerid to be set as the extension of the line \n"
" making/redirecting the outgoing call. For example, some PSTNs\n"
" don't allow callerids from other extensions then the ones\n"
" that are assigned to you.\n"
" 't' -- allow the called user transfer the calling user\n"
" 'T' -- to allow the calling user to transfer the call.\n"
" 'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
" 'm' -- provide hold music to the calling party until answered.\n"
" 'M(x) -- Executes the macro (x) upon connect of the call\n"
" 'h' -- allow callee to hang up by hitting *.\n"
" 'H' -- allow caller to hang up by hitting *.\n"
" 'C' -- reset call detail record for this call.\n"
" 'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
" 'g' -- goes on in context if the destination channel hangs up\n"
" 'A(x)' -- play an announcement to the called party, using x as file\n"
" 'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"
" 'D([digits])' -- Send DTMF digit string *after* called party has answered\n"
" but before the bridge. (w=500ms sec pause)\n"
" 'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
" repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
" The following special variables are optional:\n"
" * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
" Play sounds to the caller.\n"
" * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
" Play sounds to the callee.\n"
" * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
" * LIMIT_CONNECT_FILE File to play when call begins.\n"
" * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
" 'timeleft' is a special sound macro to auto-say the time \n"
" left and is the default.\n\n"
" In addition to transferring the call, a call may be parked and then picked\n"
"up by another user.\n"
" The optional URL will be sent to the called party if the channel supports it.\n"
" This application sets the following channel variables upon completion:\n"
" DIALEDTIME Time from dial to answer\n"
" ANSWEREDTIME Time for actual call\n"
" DIALSTATUS The status of the call as a text string, one of\n"
" CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
"";
" The optionnal URL will be sent to the called party if the channel supports\n"
"it.\n";
/* We define a customer "local user" structure because we
use it not only for keeping track of what is in use but
@@ -110,9 +83,7 @@ struct localuser {
int allowredirect_out;
int ringbackonly;
int musiconhold;
int allowdisconnect_in;
int allowdisconnect_out;
int forcecallerid;
int allowdisconnect;
struct localuser *next;
};
@@ -132,33 +103,43 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
}
}
#define AST_MAX_WATCHERS 256
#define MAX 256
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *sentringing, char *status, size_t statussize)
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect)
{
struct localuser *o;
int found;
int numlines;
int numbusy = 0;
int numcongestion = 0;
int numnochan = 0;
int sentringing = 0;
int numbusies = 0;
int orig = *to;
struct ast_frame *f;
struct ast_channel *peer = NULL;
struct ast_channel *watchers[AST_MAX_WATCHERS];
struct ast_channel *watchers[MAX];
int pos;
int single;
int moh=0;
int ringind=0;
struct ast_channel *winner;
single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
if (single) {
/* Turn off hold music, etc */
ast_deactivate_generator(in);
ast_indicate(in, -1);
/* If we are calling a single channel, make them compatible for in-band tone purpose */
ast_channel_make_compatible(outgoing->chan, in);
}
if (outgoing) {
moh = outgoing->musiconhold;
ringind = outgoing->ringbackonly;
if (outgoing->musiconhold) {
ast_moh_start(in, NULL);
} else if (outgoing->ringbackonly) {
ast_indicate(in, AST_CONTROL_RINGING);
}
}
while(*to && !peer) {
o = outgoing;
@@ -176,15 +157,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
numlines++;
}
if (found < 0) {
if (numlines == (numbusy + numcongestion + numnochan)) {
if (numlines == numbusies) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
if (numbusy)
strncpy(status, "BUSY", statussize - 1);
else if (numcongestion)
strncpy(status, "CONGESTION", statussize - 1);
else if (numnochan)
strncpy(status, "CHANUNAVAIL", statussize - 1);
ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
/* See if there is a special busy message */
if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid))
in->priority+=100;
@@ -193,6 +168,12 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
}
*to = 0;
/* if no one available we'd better stop MOH/ringing to */
if (moh) {
ast_moh_stop(in);
} else if (ringind) {
ast_indicate(in, -1);
}
return NULL;
}
winner = ast_waitfor_n(watchers, pos, to);
@@ -205,86 +186,29 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
peer = o->chan;
*allowredir_in = o->allowredirect_in;
*allowredir_out = o->allowredirect_out;
*allowdisconnect_in = o->allowdisconnect_in;
*allowdisconnect_out = o->allowdisconnect_out;
*allowdisconnect = o->allowdisconnect;
}
} else if (o->chan && (o->chan == winner)) {
if (!ast_strlen_zero(o->chan->call_forward)) {
char tmpchan[256]="";
char *stuff;
char *tech;
strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
if ((stuff = strchr(tmpchan, '/'))) {
*stuff = '\0';
stuff++;
tech = tmpchan;
} else {
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
stuff = tmpchan;
tech = "Local";
}
if (strlen(o->chan->call_forward)) {
char tmpchan[256];
/* Before processing channel, go ahead and check for forwarding */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s@%s' (thanks to %s)\n", in->name, o->chan->call_forward, o->chan->context, o->chan->name);
/* Setup parameters */
o->chan = ast_request(tech, in->nativeformats, stuff);
snprintf(tmpchan, sizeof(tmpchan),"%s@%s", o->chan->call_forward, o->chan->context);
ast_hangup(o->chan);
o->chan = ast_request("Local", in->nativeformats, tmpchan);
if (!o->chan) {
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
o->stillgoing = 0;
numnochan++;
} else {
if (o->chan->callerid)
free(o->chan->callerid);
o->chan->callerid = NULL;
if (o->forcecallerid) {
char *newcid = NULL;
if (strlen(in->macroexten))
newcid = in->macroexten;
else
newcid = in->exten;
o->chan->callerid = strdup(newcid);
strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
o->chan->cdrflags = winner->cdrflags;
if (!o->chan->callerid)
ast_log(LOG_WARNING, "Out of memory\n");
} else {
if (in->callerid) {
o->chan->callerid = strdup(in->callerid);
if (!o->chan->callerid)
ast_log(LOG_WARNING, "Out of memory\n");
}
strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
o->chan->cdrflags = in->cdrflags;
}
if (in->ani) {
if (o->chan->ani)
free(o->chan->ani);
o->chan->ani = malloc(strlen(in->ani) + 1);
if (o->chan->ani)
strncpy(o->chan->ani, in->ani, strlen(in->ani));
else
ast_log(LOG_WARNING, "Out of memory\n");
}
if (o->chan->rdnis)
free(o->chan->rdnis);
if (!ast_strlen_zero(in->macroexten))
o->chan->rdnis = strdup(in->macroexten);
else
o->chan->rdnis = strdup(in->exten);
if (ast_call(o->chan, tmpchan, 0)) {
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
o->stillgoing = 0;
ast_hangup(o->chan);
o->chan = NULL;
numnochan++;
}
numbusies++;
} else if (ast_call(o->chan, tmpchan, 0)) {
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
o->stillgoing = 0;
ast_hangup(o->chan);
o->chan = NULL;
numbusies++;
}
/* Hangup the original channel now, in case we needed it */
ast_hangup(winner);
continue;
}
f = ast_read(winner);
@@ -299,8 +223,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
peer = o->chan;
*allowredir_in = o->allowredirect_in;
*allowredir_out = o->allowredirect_out;
*allowdisconnect_in = o->allowdisconnect_in;
*allowdisconnect_out = o->allowdisconnect_out;
*allowdisconnect = o->allowdisconnect;
}
break;
case AST_CONTROL_BUSY:
@@ -312,7 +235,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
o->stillgoing = 0;
if (in->cdr)
ast_cdr_busy(in->cdr);
numbusy++;
numbusies++;
break;
case AST_CONTROL_CONGESTION:
if (option_verbose > 2)
@@ -323,32 +246,29 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
o->stillgoing = 0;
if (in->cdr)
ast_cdr_busy(in->cdr);
numcongestion++;
numbusies++;
break;
case AST_CONTROL_RINGING:
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
if (!(*sentringing) && !outgoing->musiconhold) {
if (!sentringing && !moh) {
ast_indicate(in, AST_CONTROL_RINGING);
(*sentringing)++;
sentringing++;
ringind++;
}
break;
case AST_CONTROL_PROGRESS:
if (option_verbose > 2)
ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
if (!outgoing->ringbackonly)
ast_indicate(in, AST_CONTROL_PROGRESS);
ast_indicate(in, AST_CONTROL_PROGRESS);
break;
case AST_CONTROL_OFFHOOK:
/* Ignore going off hook */
break;
case -1:
if (!outgoing->ringbackonly && !outgoing->musiconhold) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
ast_indicate(in, -1);
(*sentringing) = 0;
}
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
ast_indicate(in, -1);
break;
default:
ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
@@ -383,18 +303,13 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
/* Got hung up */
*to=-1;
strncpy(status, "CANCEL", statussize - 1);
if (f)
ast_frfree(f);
return NULL;
}
if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
(f->subclass == '*')) {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
*to=0;
strcpy(status, "CANCEL");
ast_frfree(f);
return NULL;
}
if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) {
@@ -406,6 +321,11 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
if (!*to && (option_verbose > 2))
ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
}
if (moh) {
ast_moh_stop(in);
} else if (ringind) {
ast_indicate(in, -1);
}
return peer;
@@ -415,7 +335,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
char *info, *peers, *timeout, *tech, *number, *rest, *cur;
char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
char privdb[256] = "", *s;
char announcemsg[256] = "", *ann;
struct localuser *outgoing=NULL, *tmp;
@@ -423,59 +343,32 @@ static int dial_exec(struct ast_channel *chan, void *data)
int to;
int allowredir_in=0;
int allowredir_out=0;
int allowdisconnect_in=0;
int allowdisconnect_out=0;
int hasmacro = 0;
int allowdisconnect=0;
int privacy=0;
int announce=0;
int resetcdr=0;
int cnt=0;
char numsubst[AST_MAX_EXTENSION];
char restofit[AST_MAX_EXTENSION];
char *transfer = NULL;
char *newnum;
char callerid[256] = "", *l, *n;
char callerid[256], *l, *n;
char *url=NULL; /* JDG */
struct ast_var_t *current;
struct varshead *headp, *newheadp;
struct ast_var_t *newvar;
int go_on=0;
unsigned int calldurationlimit=0;
char *cdl;
time_t now;
struct ast_bridge_config config;
long timelimit = 0;
long play_warning = 0;
long warning_freq=0;
char *warning_sound=NULL;
char *end_sound=NULL;
char *start_sound=NULL;
char *limitptr;
char limitdata[256];
char *sdtmfptr;
char sdtmfdata[256] = "";
char *stack,*var;
char *mac = NULL, macroname[256] = "";
char status[256]="";
char toast[80];
int play_to_caller=0,play_to_callee=0;
int playargs=0, sentringing=0, moh=0;
int digit = 0;
time_t start_time, answer_time, end_time;
if (!data) {
ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
return -1;
}
if (!(info = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Unable to dupe data :(\n");
ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n");
return -1;
}
LOCAL_USER_ADD(u);
strncpy(info, (char *)data, sizeof(info) - 1);
peers = info;
if (peers) {
timeout = strchr(info, '|');
if (timeout) {
*timeout = '\0';
@@ -497,150 +390,13 @@ static int dial_exec(struct ast_channel *chan, void *data)
}
} else
timeout = NULL;
if (!peers || ast_strlen_zero(peers)) {
if (!peers || !strlen(peers)) {
ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
goto out;
}
if (transfer) {
/* Extract call duration limit */
if ((cdl = strstr(transfer, "S("))) {
calldurationlimit=atoi(cdl+2);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);
}
/* DTMF SCRIPT*/
if ((sdtmfptr = strstr(transfer, "D("))) {
strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
/* Overwrite with X's what was the sdtmf info */
while (*sdtmfptr && (*sdtmfptr != ')'))
*(sdtmfptr++) = 'X';
if (*sdtmfptr)
*sdtmfptr = 'X';
/* Now find the end */
sdtmfptr = strchr(sdtmfdata, ')');
if (sdtmfptr)
*sdtmfptr = '\0';
else
ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
}
/* XXX LIMIT SUPPORT */
if ((limitptr = strstr(transfer, "L("))) {
strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
/* Overwrite with X's what was the limit info */
while(*limitptr && (*limitptr != ')'))
*(limitptr++) = 'X';
if (*limitptr)
*limitptr = 'X';
/* Now find the end */
limitptr = strchr(limitdata, ')');
if (limitptr)
*limitptr = '\0';
else
ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
play_to_caller = var ? ast_true(var) : 1;
var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
play_to_callee = var ? ast_true(var) : 0;
if (!play_to_caller && !play_to_callee)
play_to_caller=1;
var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
warning_sound = var ? var : "timeleft";
var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
end_sound = var ? var : NULL;
var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
start_sound = var ? var : NULL;
var=stack=limitdata;
var = strsep(&stack, ":");
if (var) {
timelimit = atol(var);
playargs++;
var = strsep(&stack, ":");
if (var) {
play_warning = atol(var);
playargs++;
var = strsep(&stack, ":");
if(var) {
warning_freq = atol(var);
playargs++;
}
}
}
if (!timelimit) {
timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
warning_sound=NULL;
}
/* undo effect of S(x) in case they are both used */
calldurationlimit=0;
/* more efficient do it like S(x) does since no advanced opts*/
if (!play_warning && !start_sound && !end_sound && timelimit) {
calldurationlimit=timelimit/1000;
timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
} else if (option_verbose > 2) {
ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
}
}
/* XXX ANNOUNCE SUPPORT */
if ((ann = strstr(transfer, "A("))) {
announce = 1;
strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
/* Overwrite with X's what was the announce info */
while(*ann && (*ann != ')'))
*(ann++) = 'X';
if (*ann)
*ann = 'X';
/* Now find the end of the privdb */
ann = strchr(announcemsg, ')');
if (ann)
*ann = '\0';
else {
ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
announce = 0;
}
}
/* Get the macroname from the dial option string */
if ((mac = strstr(transfer, "M("))) {
hasmacro = 1;
strncpy(macroname, mac + 2, sizeof(macroname) - 1);
while (*mac && (*mac != ')'))
*(mac++) = 'X';
if (*mac)
*mac = 'X';
else {
ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
hasmacro = 0;
}
mac = strchr(macroname, ')');
if (mac)
*mac = '\0';
else {
ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
hasmacro = 0;
}
}
/* Extract privacy info from transfer */
if ((s = strstr(transfer, "P("))) {
privacy = 1;
@@ -655,7 +411,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
if (s)
*s = '\0';
else {
ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
ast_log(LOG_WARNING, "Transfer with privacy lacking trailing '('\n");
privacy = 0;
}
} else if (strchr(transfer, 'P')) {
@@ -664,18 +420,28 @@ static int dial_exec(struct ast_channel *chan, void *data)
} else if (strchr(transfer, 'C')) {
resetcdr = 1;
}
/* XXX ANNOUNCE SUPPORT */
else if ((ann = strstr(transfer, "A("))) {
announce = 1;
strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
cnt=0;
while(announcemsg[cnt] != ')') {
cnt++;
}
announcemsg[cnt]='\0';
}
}
if (resetcdr && chan->cdr)
ast_cdr_reset(chan->cdr, 0);
if (ast_strlen_zero(privdb) && privacy) {
if (!strlen(privdb) && privacy) {
/* If privdb is not specified and we are using privacy, copy from extension */
strncpy(privdb, chan->exten, sizeof(privdb) - 1);
}
if (privacy) {
if (chan->callerid)
strncpy(callerid, chan->callerid, sizeof(callerid) - 1);
strncpy(callerid, chan->callerid, sizeof(callerid));
else
callerid[0] = '\0';
strcpy(callerid, "");
ast_callerid_parse(callerid, &n, &l);
if (l) {
ast_shrink_phone_number(l);
@@ -720,16 +486,10 @@ static int dial_exec(struct ast_channel *chan, void *data)
tmp->musiconhold = 1;
else tmp->musiconhold = 0;
if (strchr(transfer, 'H'))
allowdisconnect_out = tmp->allowdisconnect_out = 1;
else allowdisconnect_out = tmp->allowdisconnect_out = 0;
if(strchr(transfer, 'h'))
allowdisconnect_in = tmp->allowdisconnect_in = 1;
else allowdisconnect_in = tmp->allowdisconnect_in = 0;
allowdisconnect = tmp->allowdisconnect = 1;
else allowdisconnect = tmp->allowdisconnect = 0;
if(strchr(transfer, 'g'))
go_on=1;
if (strchr(transfer, 'f'))
tmp->forcecallerid = 1;
else tmp->forcecallerid = 0;
}
strncpy(numsubst, number, sizeof(numsubst)-1);
/* If we're dialing by extension, look at the extension to know what to dial */
@@ -750,29 +510,15 @@ static int dial_exec(struct ast_channel *chan, void *data)
cur = rest;
continue;
}
pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
if (!ast_strlen_zero(tmp->chan->call_forward)) {
char tmpchan[256]="";
char *stuff;
char *tech;
strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
if ((stuff = strchr(tmpchan, '/'))) {
*stuff = '\0';
stuff++;
tech = tmpchan;
} else {
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
stuff = tmpchan;
tech = "Local";
}
/* Before processing channel, go ahead and check for forwarding */
if (strlen(tmp->chan->call_forward)) {
char tmpchan[256];
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
/* Setup parameters */
ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context);
ast_hangup(tmp->chan);
tmp->chan = ast_request(tech, chan->nativeformats, stuff);
tmp->chan = ast_request("Local", chan->nativeformats, tmpchan);
if (!tmp->chan) {
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
free(tmp);
cur = rest;
continue;
@@ -781,21 +527,36 @@ static int dial_exec(struct ast_channel *chan, void *data)
/* If creating a SIP channel, look for a variable called */
/* VXML_URL in the calling channel and copy it to the */
/* new channel. */
if (strcasecmp(tech,"SIP")==0)
{
headp=&chan->varshead;
AST_LIST_TRAVERSE(headp,current,entries) {
if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
{
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
newheadp=&tmp->chan->varshead;
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
break;
}
}
}
/* Check for ALERT_INFO in the SetVar list. This is for */
/* SIP distinctive ring as per the RFC. For Cisco 7960s, */
/* SetVar(ALERT_INFO=<x>) where x is an integer value 1-5. */
/* However, the RFC says it should be a URL. -km- */
headp=&chan->varshead;
AST_LIST_TRAVERSE(headp,current,entries) {
if (!strcasecmp(ast_var_name(current),"VXML_URL") ||
!strcasecmp(ast_var_name(current), "ALERT_INFO") ||
!strcasecmp(ast_var_name(current), "OSPTOKEN") ||
!strcasecmp(ast_var_name(current), "OSPHANDLE"))
{
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
newheadp=&tmp->chan->varshead;
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
if (strcasecmp(tech,"SIP")==0)
{
headp=&chan->varshead;
AST_LIST_TRAVERSE(headp,current,entries) {
/* Search for ALERT_INFO */
if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
{
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
newheadp=&tmp->chan->varshead;
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
break;
}
}
}
@@ -811,10 +572,8 @@ static int dial_exec(struct ast_channel *chan, void *data)
else
tmp->chan->callerid = NULL;
/* Copy language from incoming to outgoing */
strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
tmp->chan->cdrflags = chan->cdrflags;
if (ast_strlen_zero(tmp->chan->musicclass))
strcpy(tmp->chan->language, chan->language);
if (!strlen(tmp->chan->musicclass))
strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
if (chan->ani)
tmp->chan->ani = strdup(chan->ani);
@@ -835,7 +594,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
if (chan->cdr)
ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
/* check the results of ast_call */
/* check the restuls of ast_call */
if (res) {
/* Again, keep going even if there's an error */
if (option_debug)
@@ -861,31 +620,11 @@ static int dial_exec(struct ast_channel *chan, void *data)
cur = rest;
} while(cur);
if (timeout && !ast_strlen_zero(timeout)) {
to = atoi(timeout);
if (to > 0)
to *= 1000;
else
ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
} else
if (timeout && strlen(timeout))
to = atoi(timeout) * 1000;
else
to = -1;
if (outgoing) {
/* Our status will at least be NOANSWER */
strncpy(status, "NOANSWER", sizeof(status) - 1);
if (outgoing->musiconhold) {
moh=1;
ast_moh_start(chan, NULL);
} else if (outgoing->ringbackonly) {
ast_indicate(chan, AST_CONTROL_RINGING);
sentringing++;
}
} else
strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
time(&start_time);
peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status));
peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect);
if (!peer) {
if (to)
/* Musta gotten hung up */
@@ -897,12 +636,6 @@ static int dial_exec(struct ast_channel *chan, void *data)
goto out;
}
if (peer) {
time(&answer_time);
#ifdef OSP_SUPPORT
/* Once call is answered, ditch the OSP Handle */
pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
#endif
strncpy(status, "ANSWER", sizeof(status) - 1);
/* Ah ha! Someone answered within the desired timeframe. Of course after this
we will always return with -1 so that it is hung up properly after the
conversation. */
@@ -913,131 +646,43 @@ static int dial_exec(struct ast_channel *chan, void *data)
ast_cdr_setdestchan(chan->cdr, peer->name);
if (peer->name)
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
if (!number)
number = numsubst;
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
if (numsubst)
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
/* Make sure channels are compatible */
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
ast_hangup(peer);
return -1;
}
/* JDG: sendurl */
if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
if( url && strlen(url) && ast_channel_supports_html(peer) ) {
ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
ast_channel_sendurl( peer, url );
} /* /JDG */
if (announce && announcemsg) {
if (announce && announcemsg)
{
int res2;
// Start autoservice on the other chan
res = ast_autoservice_start(chan);
res2 = ast_autoservice_start(chan);
// Now Stream the File
if (!res)
res = ast_streamfile(peer,announcemsg,peer->language);
if (!res) {
digit = ast_waitstream(peer, AST_DIGIT_ANY);
}
if (!res2)
res2 = ast_streamfile(peer,announcemsg,peer->language);
if (!res2)
res2 = ast_waitstream(peer,"");
// Ok, done. stop autoservice
res = ast_autoservice_stop(chan);
if (digit > 0 && !res)
res = ast_senddigit(chan, digit);
else
res = digit;
} else
res = 0;
if (hasmacro && macroname) {
void *app = NULL;
res = ast_autoservice_start(chan);
if (res) {
ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
res = -1;
}
app = pbx_findapp("Macro");
if (app && !res) {
res = pbx_exec(peer, app, macroname, 1);
ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
res = 0;
} else {
ast_log(LOG_ERROR, "Could not find application Macro\n");
res = -1;
}
if (ast_autoservice_stop(chan) < 0) {
ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
res = -1;
}
res2 = ast_autoservice_stop(chan);
}
res = ast_bridge_call(chan, peer, allowredir_in, allowredir_out, allowdisconnect);
if (!res) {
if (calldurationlimit > 0) {
time(&now);
chan->whentohangup = now + calldurationlimit;
}
if (!ast_strlen_zero(sdtmfdata))
res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
}
if (!res) {
memset(&config,0,sizeof(struct ast_bridge_config));
config.play_to_caller=play_to_caller;
config.play_to_callee=play_to_callee;
config.allowredirect_in = allowredir_in;
config.allowredirect_out = allowredir_out;
config.allowdisconnect_in = allowdisconnect_in;
config.allowdisconnect_out = allowdisconnect_out;
config.timelimit = timelimit;
config.play_warning = play_warning;
config.warning_freq = warning_freq;
config.warning_sound = warning_sound;
config.end_sound = end_sound;
config.start_sound = start_sound;
if (moh) {
moh = 0;
ast_moh_stop(chan);
} else if (sentringing) {
sentringing = 0;
ast_indicate(chan, -1);
}
/* Be sure no generators are left on it */
ast_deactivate_generator(chan);
/* Make sure channels are compatible */
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
ast_hangup(peer);
return -1;
}
res = ast_bridge_call(chan,peer,&config);
time(&end_time);
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
} else
res = -1;
if (res != AST_PBX_NO_HANGUP_PEER) {
if (!chan->_softhangup)
chan->hangupcause = peer->hangupcause;
if (res != AST_PBX_NO_HANGUP_PEER)
ast_hangup(peer);
}
}
out:
if (moh) {
moh = 0;
ast_moh_stop(chan);
} else if (sentringing) {
sentringing = 0;
ast_indicate(chan, -1);
}
hanguptree(outgoing, NULL);
pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
LOCAL_USER_REMOVE(u);
if((go_on>0) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
if((go_on>0) && (!chan->_softhangup))
res=0;
return res;

View File

@@ -19,10 +19,10 @@
#include <asterisk/module.h>
#include <asterisk/config.h>
#include <asterisk/say.h>
#include <asterisk/utils.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include "../asterisk.h"
#include "../astconf.h"
@@ -32,15 +32,12 @@ static char *app = "Directory";
static char *synopsis = "Provide directory of voicemail extensions";
static char *descrip =
" Directory(vm-context[|dial-context[|options]]): Presents the user with a directory\n"
"of extensions from which they may select by name. The list of names \n"
"and extensions is discovered from voicemail.conf. The vm-context argument\n"
"is required, and specifies the context of voicemail.conf to use. The\n"
"dial-context is the context to use for dialing the users, and defaults to\n"
"the vm-context if unspecified. The 'f' option causes the directory to match\n"
"based on the first name in voicemail.conf instead of the last name.\n"
"Returns 0 unless the user hangs up. It also sets up the channel on exit\n"
"to enter the extension the user selected.\n";
" Directory(context): Presents the user with a directory of extensions from\n"
"which they may select by name. The list of names and extensions is\n"
"discovered from voicemail.conf. The context argument is required, and\n"
"specifies the context in which to interpret the extensions. Returns 0\n"
"unless the user hangs up. It also sets up the channel on exit to enter the\n"
"extension the user selected.\n";
/* For simplicity, I'm keeping the format compatible with the voicemail config,
but i'm open to suggestions for isolating it */
@@ -123,108 +120,18 @@ static char *convert(char *lastname)
return tmp;
}
/* play name of mailbox owner.
* returns: -1 for bad or missing extension
* '1' for selected entry from directory
* '*' for skipped entry from directory
*/
static int play_mailbox_owner(struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name) {
int res = 0;
int loop = 3;
char fn[256];
char fn2[256];
/* Check for the VoiceMail2 greeting first */
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
(char *)ast_config_AST_SPOOL_DIR, context, ext);
/* Otherwise, check for an old-style Voicemail greeting */
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
(char *)ast_config_AST_SPOOL_DIR, ext);
if (ast_fileexists(fn, NULL, chan->language) > 0) {
res = ast_streamfile(chan, fn, chan->language);
if (!res) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
}
ast_stopstream(chan);
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
res = ast_streamfile(chan, fn2, chan->language);
if (!res) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
}
ast_stopstream(chan);
} else {
res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext,
AST_DIGIT_ANY, chan->language);
}
while (loop) {
if (!res) {
res = ast_streamfile(chan, "dir-instr", chan->language);
}
if (!res) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
}
if (!res) {
res = ast_waitfordigit(chan, 3000);
}
ast_stopstream(chan);
if (res > -1) {
switch (res) {
case '1':
/* Name selected */
loop = 0;
if (ast_exists_extension(chan,dialcontext,ext,1,chan->callerid)) {
strncpy(chan->exten, ext, sizeof(chan->exten)-1);
chan->priority = 0;
strncpy(chan->context, dialcontext, sizeof(chan->context)-1);
} else {
ast_log(LOG_WARNING,
"Can't find extension '%s' in context '%s'. "
"Did you pass the wrong context to Directory?\n",
ext, dialcontext);
res = -1;
}
break;
case '*':
/* Skip to next match in list */
loop = 0;
break;
default:
/* Not '1', or '*', so decrement number of tries */
res = 0;
loop--;
break;
} /* end switch */
} /* end if */
else {
/* User hungup, so jump out now */
loop = 0;
}
} /* end while */
return(res);
}
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last)
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char digit)
{
/* Read in the first three digits.. "digit" is the first digit, already read */
char ext[NUMDIGITS + 1];
char name[80] = "";
struct ast_variable *v;
int res;
int found=0;
int lastuserchoice = 0;
char *start, *pos, *conv,*stringp=NULL;
if (!context || ast_strlen_zero(context)) {
ast_log(LOG_WARNING,
"Directory must be called with an argument "
"(context in which to interpret extensions)\n");
char fn[256];
char fn2[256];
if (!context || !strlen(context)) {
ast_log(LOG_WARNING, "Directory must be called with an argument (context in which to interpret extensions)\n");
return -1;
}
memset(ext, 0, sizeof(ext));
@@ -244,9 +151,8 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
strsep(&stringp, ",");
pos = strsep(&stringp, ",");
if (pos) {
strncpy(name, pos, sizeof(name) - 1);
/* Grab the last name */
if (last && strrchr(pos,' '))
if (strrchr(pos, ' '))
pos = strrchr(pos, ' ') + 1;
conv = convert(pos);
if (conv) {
@@ -264,46 +170,59 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
}
v = v->next;
}
if (v) {
/* We have a match -- play a greeting if they have it */
res = play_mailbox_owner(chan, context, dialcontext, v->name, name);
switch (res) {
case -1:
/* user pressed '1' but extension does not exist, or
* user hungup
*/
lastuserchoice = 0;
break;
case '1':
/* user pressed '1' and extensions exists */
lastuserchoice = res;
strncpy(chan->context, dialcontext, sizeof(chan->context) - 1);
strncpy(chan->exten, v->name, sizeof(chan->exten) - 1);
/* Check for the VoiceMail2 greeting first */
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", (char *)ast_config_AST_SPOOL_DIR, context, v->name);
/* Otherwise, check for an old-style Voicemail greeting */
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet", (char *)ast_config_AST_SPOOL_DIR, v->name);
if (ast_fileexists(fn, NULL, chan->language) > 0) {
res = ast_streamfile(chan, fn, chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
res = ast_streamfile(chan, fn2, chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
} else {
res = ast_say_digit_str(chan, v->name, AST_DIGIT_ANY, chan->language);
}
ahem:
if (!res)
res = ast_streamfile(chan, "dir-instr", chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
if (!res)
res = ast_waitfordigit(chan, 3000);
ast_stopstream(chan);
if (res > -1) {
if (res == '1') {
strncpy(chan->exten, v->name, sizeof(chan->exten)-1);
chan->priority = 0;
break;
case '*':
/* user pressed '*' to skip something found */
lastuserchoice = res;
strncpy(chan->context, context, sizeof(chan->context)-1);
res = 0;
break;
default:
break;
} else if (res == '*') {
res = 0;
v = v->next;
} else {
res = 0;
goto ahem;
}
}
v = v->next;
} else {
if (found)
res = ast_streamfile(chan, "dir-nomore", chan->language);
else
res = ast_streamfile(chan, "dir-nomatch", chan->language);
if (!res)
res = 1;
return res;
}
}
if (lastuserchoice != '1') {
if (found)
res = ast_streamfile(chan, "dir-nomore", chan->language);
else
res = ast_streamfile(chan, "dir-nomatch", chan->language);
if (!res)
res = 1;
return res;
}
return 0;
}
return res;
}
@@ -313,11 +232,8 @@ static int directory_exec(struct ast_channel *chan, void *data)
int res = 0;
struct localuser *u;
struct ast_config *cfg;
int last = 1;
char *context, *dialcontext, *dirintro, *options;
if (!data) {
ast_log(LOG_WARNING, "directory requires an argument (context[,dialcontext])\n");
ast_log(LOG_WARNING, "directory requires an argument (context)\n");
return -1;
}
cfg = ast_load(DIRECTORY_CONFIG);
@@ -327,40 +243,17 @@ static int directory_exec(struct ast_channel *chan, void *data)
}
LOCAL_USER_ADD(u);
top:
context = ast_strdupa(data);
dialcontext = strchr(context, '|');
if (dialcontext) {
*dialcontext = '\0';
dialcontext++;
options = strchr(dialcontext, '|');
if (options) {
*options = '\0';
options++;
if (strchr(options, 'f'))
last = 0;
}
} else
dialcontext = context;
dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
if (!dirintro || ast_strlen_zero(dirintro))
dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
if (!dirintro || ast_strlen_zero(dirintro)) {
if (last)
dirintro = "dir-intro";
else
dirintro = "dir-intro-fn";
}
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (!res)
res = ast_streamfile(chan, dirintro, chan->language);
res = ast_streamfile(chan, "dir-intro", chan->language);
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
if (!res)
res = ast_waitfordigit(chan, 5000);
if (res > 0) {
res = do_directory(chan, cfg, context, dialcontext, res, last);
res = do_directory(chan, cfg, (char *)data, res);
if (res > 0) {
res = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);

View File

@@ -17,7 +17,6 @@
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/indications.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
@@ -26,8 +25,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <sys/time.h>
/*
#define TONE_BLOCK_SIZE 320
*/
static char *tdesc = "DISA (Direct Inward System Access) Application";
@@ -80,9 +83,27 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static float loudness=4096.0;
static int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
static int digittimeout = 10000; /* 10 seconds subsequent digit timeout */
static void make_tone_block(unsigned char *data, float f1, float f2, int len, int *x)
{
int i;
float val;
for(i = 0; i < len; i++)
{
val = loudness * sin((f1 * 2.0 * M_PI * (*x))/8000.0);
val += loudness * sin((f2 * 2.0 * M_PI * (*x)++)/8000.0);
data[i] = AST_LIN2MU((int)val);
}
/* wrap back around from 8000 */
if (*x >= 8000) *x = 0;
return;
}
static int ms_diff(struct timeval *tv1, struct timeval *tv2)
{
int ms;
@@ -92,26 +113,19 @@ int ms;
return(ms);
}
static void play_dialtone(struct ast_channel *chan)
{
const struct tone_zone_sound *ts = NULL;
ts = ast_get_indication_tone(chan->zone, "dial");
if (ts)
ast_playtones_start(chan, 0, ts->data, 0);
else
ast_tonepair_start(chan, 350, 440, 0, 0);
}
static int disa_exec(struct ast_channel *chan, void *data)
{
int i,j,k,x,did_ignore;
int i,j,k,x;
struct localuser *u;
char tmp[256],arg2[256]="",exten[AST_MAX_EXTENSION],acctcode[20]="";
char tmp[256],arg2[256],exten[AST_MAX_EXTENSION],acctcode[20];
struct {
unsigned char offset[AST_FRIENDLY_OFFSET];
unsigned char buf[640];
} tone_block;
char *ourcontext,*ourcallerid;
struct ast_frame *f;
struct ast_frame *f,wf;
struct timeval lastout, now, lastdigittime;
int res;
time_t rstart;
FILE *fp;
char *stringp=NULL;
@@ -136,7 +150,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
ourcontext = strsep(&stringp, "|");
/* if context specified, save 2nd arg and parse third */
if (ourcontext) {
strncpy(arg2,ourcontext, sizeof(arg2) - 1);
strcpy(arg2,ourcontext);
ourcallerid = strsep(&stringp,"|");
}
/* if context not specified, use "disa" */
@@ -152,22 +166,15 @@ static int disa_exec(struct ast_channel *chan, void *data)
ast_answer(chan);
}
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
did_ignore = 0;
exten[0] = 0;
acctcode[0] = 0;
/* can we access DISA without password? */
ast_log(LOG_DEBUG, "Context: %s\n",ourcontext);
if (!strcasecmp(tmp, "no-password"))
{;
k = 1;
ast_log(LOG_DEBUG, "DISA no-password login success\n");
}
gettimeofday(&lastdigittime,NULL);
play_dialtone(chan);
for(;;)
{
gettimeofday(&now,NULL);
@@ -198,7 +205,24 @@ static int disa_exec(struct ast_channel *chan, void *data)
return -1;
}
if (f->frametype == AST_FRAME_VOICE) {
ast_frfree(f);
if (!i || (ast_ignore_pattern(ourcontext, exten) && k)) {
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = tone_block.buf;
wf.datalen = f->datalen;
make_tone_block(tone_block.buf, 350, 440, f->datalen, &x);
wf.samples = wf.datalen;
ast_frfree(f);
if (ast_write(chan, &wf))
{
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
} else
ast_frfree(f);
continue;
}
/* if not DTMF, just do it again */
@@ -210,9 +234,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
j = f->subclass; /* save digit */
ast_frfree(f);
if (i == 0)
ast_playtones_stop(chan);
gettimeofday(&lastdigittime,NULL);
/* got a DTMF tone */
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
@@ -265,52 +287,38 @@ static int disa_exec(struct ast_channel *chan, void *data)
}
/* password good, set to dial state */
ast_log(LOG_DEBUG,"DISA on chan %s password is good\n",chan->name);
play_dialtone(chan);
ast_log(LOG_WARNING,"DISA on chan %s password is good\n",chan->name);
k = 1;
i = 0; /* re-set buffer pointer */
exten[sizeof(acctcode)] = 0;
strncpy(acctcode,exten, sizeof(acctcode) - 1);
strcpy(acctcode,exten);
exten[0] = 0;
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
continue;
}
}
exten[i++] = j; /* save digit */
exten[i] = 0;
if (!k) continue; /* if getting password, continue doing it */
/* if this exists */
if (ast_ignore_pattern(ourcontext, exten)) {
play_dialtone(chan);
did_ignore = 1;
} else
if (did_ignore) {
ast_playtones_stop(chan);
did_ignore = 0;
}
/* if can do some more, do it */
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid)) {
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid))
break;
}
}
}
if (k && ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
{
ast_playtones_stop(chan);
/* We're authenticated and have a valid extension */
if (ourcallerid && *ourcallerid)
{
if (chan->callerid) free(chan->callerid);
chan->callerid = strdup(ourcallerid);
}
strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
strncpy(chan->context, ourcontext, sizeof(chan->context) - 1);
strncpy(chan->accountcode, acctcode, sizeof(chan->accountcode) - 1);
strcpy(chan->exten,exten);
strcpy(chan->context,ourcontext);
strcpy(chan->accountcode,acctcode);
chan->priority = 0;
ast_cdr_init(chan->cdr,chan);
LOCAL_USER_REMOVE(u);
@@ -318,20 +326,44 @@ static int disa_exec(struct ast_channel *chan, void *data)
}
reorder:
ast_indicate(chan,AST_CONTROL_CONGESTION);
/* something is invalid, give em reorder for several seconds */
time(&rstart);
while(time(NULL) < rstart + 10)
/* something is invalid, give em reorder forever */
x = 0;
k = 0; /* k = 0 means busy tone, k = 1 means silence) */
i = 0; /* Number of samples we've done */
for(;;)
{
if (ast_waitfor(chan, -1) < 0)
break;
f = ast_read(chan);
if (!f)
break;
if (f->frametype == AST_FRAME_VOICE) {
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = tone_block.buf;
wf.datalen = f->datalen;
wf.samples = wf.datalen;
if (k)
memset(tone_block.buf, 0x7f, wf.datalen);
else
make_tone_block(tone_block.buf,480.0, 620.0,wf.datalen, &x);
i += wf.datalen / 8;
if (i > 250) {
i = 0;
k = !k;
}
if (ast_write(chan, &wf))
{
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
}
ast_frfree(f);
}
ast_playtones_stop(chan);
LOCAL_USER_REMOVE(u);
return -1;
}

View File

@@ -22,6 +22,9 @@
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Simple Echo Application";
static char *app = "Echo";
@@ -49,8 +52,6 @@ static int echo_exec(struct ast_channel *chan, void *data)
f = ast_read(chan);
if (!f)
break;
f->delivery.tv_sec = 0;
f->delivery.tv_usec = 0;
if (f->frametype == AST_FRAME_VOICE) {
if (ast_write(chan, f))
break;

View File

@@ -20,13 +20,15 @@
#include <asterisk/config.h>
#include <asterisk/module.h>
#include <asterisk/enum.h>
#include <asterisk/utils.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <pthread.h>
static char *tdesc = "ENUM Lookup";
static char *app = "EnumLookup";
@@ -47,7 +49,7 @@ static char *descrip =
#define ENUM_CONFIG "enum.conf"
static char h323driver[80] = "";
static char h323driver[80];
#define H323DRIVERDEFAULT "H323"
STANDARD_LOCAL_USER;
@@ -62,7 +64,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
char tmp[256];
char *c,*t;
struct localuser *u;
if (!data || ast_strlen_zero(data)) {
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
res = 1;
}
@@ -126,7 +128,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
else
res = 0;
}
} else if (!ast_strlen_zero(tech)) {
} else if (strlen(tech)) {
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
res = 0;
}
@@ -148,9 +150,9 @@ static int load_config(void)
cfg = ast_load(ENUM_CONFIG);
if (cfg) {
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
strcpy(h323driver, H323DRIVERDEFAULT);
} else {
strncpy(h323driver, s, sizeof(h323driver) - 1);
strcpy(h323driver, s);
}
ast_destroy(cfg);
return 0;

View File

@@ -1,101 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Eval application
*
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_eval__v001@the-tilghman.com>
*
* $Id$
*
* This code is released by the author with no restrictions on usage.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
/* Maximum length of any variable */
#define MAXRESULT 1024
static char *tdesc = "Reevaluates strings";
static char *app_eval = "Eval";
static char *eval_synopsis = "Eval(newvar=somestring)";
static char *eval_descrip =
"Eval(newvar=somestring)\n"
" Normally Asterisk evaluates variables inline. But what if you want to\n"
"store variable offsets in a database, to be evaluated later? Eval is\n"
"the answer, by allowing a string to be evaluated twice in the dialplan,\n"
"the first time as part of the normal dialplan, and the second using Eval.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int eval_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *newvar=NULL, tmp[MAXRESULT];
LOCAL_USER_ADD(u);
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
newvar = strsep(&s, "=");
if (newvar && (newvar[0] != '\0')) {
memset(tmp, 0, MAXRESULT);
pbx_substitute_variables_helper(chan, s, tmp, MAXRESULT - 1);
pbx_builtin_setvar_helper(chan, newvar, tmp);
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
}
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app_eval);
}
int load_module(void)
{
return ast_register_application(app_eval, eval_exec, eval_synopsis, eval_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,113 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Exec application
*
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_exec__v001@the-tilghman.com>
*
* $Id$
*
* This code is released by the author with no restrictions on usage.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
/* Maximum length of any variable */
#define MAXRESULT 1024
static char *tdesc = "Executes applications";
static char *app_exec = "Exec";
static char *exec_synopsis = "Exec(Appname(arguments))";
static char *exec_descrip =
"Exec(appname(arguments))\n"
" Allows an arbitrary application to be invoked even when not\n"
"hardcoded into the dialplan. Returns whatever value the\n"
"app returns or -2 when the app cannot be found.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int exec_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *appname, *endargs, args[MAXRESULT];
struct ast_app *app;
LOCAL_USER_ADD(u);
memset(args, 0, MAXRESULT);
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
appname = strsep(&s, "(");
if (s) {
endargs = strrchr(s, ')');
if (endargs)
*endargs = '\0';
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
}
if (appname) {
app = pbx_findapp(appname);
if (app) {
res = pbx_exec(chan, app, args, 1);
} else {
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
res = -2;
}
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
}
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app_exec);
}
int load_module(void)
{
return ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -5,7 +5,7 @@
*
* Copyright (C) 2002, Christos Ricudis
*
* Christos Ricudis <ricudis@itc.auth.gr>
* Christos Ricudis <ricudis@paiko.gr>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -19,8 +19,6 @@
#include <asterisk/module.h>
#include <asterisk/md5.h>
#include <asterisk/config.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
@@ -36,6 +34,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <pthread.h>
#define FESTIVAL_CONFIG "festival.conf"
@@ -156,9 +155,6 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
return -1;
}
/* Answer if it's not already going */
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
ast_stopstream(chan);
owriteformat = chan->writeformat;
@@ -199,7 +195,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
needed = f->samples * 2;
if (needed > sizeof(myf.frdata)) {
ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
(int)sizeof(myf.frdata) / 2, needed/2);
sizeof(myf.frdata) / 2, needed/2);
needed = sizeof(myf.frdata);
}
res = read(fds[0], myf.frdata, needed);
@@ -251,7 +247,6 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
struct localuser *u;
struct sockaddr_in serv_addr;
struct hostent *serverhost;
struct ast_hostent ahp;
int fd;
FILE *fs;
char *host;
@@ -268,9 +263,9 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
int i;
struct MD5Context md5ctx;
unsigned char MD5Res[16];
char MD5Hex[33] = "";
char koko[4] = "";
char cachefile[MAXFESTLEN]="";
char MD5Hex[32];
char koko[4];
char cachefile[MAXFESTLEN];
int readcache=0;
int writecache=0;
int strln;
@@ -305,9 +300,11 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
}
if (!vdata || ast_strlen_zero(vdata)) {
if (!vdata || !strlen(vdata)) {
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
ast_destroy(cfg);
return -1;
}
strncpy(data, vdata, sizeof(data) - 1);
@@ -325,16 +322,14 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
if (fd < 0) {
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
ast_destroy(cfg);
return -1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
/* its a name rather than an ipnum */
serverhost = ast_gethostbyname(host, &ahp);
serverhost = gethostbyname(host);
if (serverhost == (struct hostent *)0) {
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
ast_destroy(cfg);
return -1;
}
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
@@ -344,7 +339,6 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
ast_destroy(cfg);
return -1;
}
@@ -352,21 +346,21 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
MD5Init(&md5ctx);
MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
MD5Final(MD5Res,&md5ctx);
MD5Hex[0] = '\0';
strcpy(MD5Hex,"");
/* Convert to HEX and look if there is any matching file in the cache
directory */
for (i=0;i<16;i++) {
snprintf(koko, sizeof(koko), "%X",MD5Res[i]);
strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
sprintf(koko,"%X",MD5Res[i]);
strcat(MD5Hex,koko);
}
readcache=0;
writecache=0;
if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
sprintf(cachefile,"%s/%s",cachedir,MD5Hex);
fdesc=open(cachefile,O_RDWR);
if (fdesc==-1) {
fdesc=open(cachefile,O_CREAT|O_RDWR,0777);
fdesc=open(cachefile,O_CREAT|O_RDWR,0);
if (fdesc!=-1) {
writecache=1;
strln=strlen((char *)data);
@@ -378,12 +372,11 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
}
} else {
read(fdesc,&strln,sizeof(int));
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,strlen((char *)data));
if (strlen((char *)data)==strln) {
ast_log(LOG_DEBUG,"Size OK\n");
read(fdesc,&bigstring,strln);
bigstring[strln] = 0;
if (strcmp(bigstring,data)==0) {
if (strcmp(bigstring,data)==0) {
readcache=1;
} else {
ast_log(LOG_WARNING,"Strings do not match\n");
@@ -447,7 +440,6 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
}
} while (strcmp(ack,"OK\n") != 0);
close(fd);
ast_destroy(cfg);
LOCAL_USER_REMOVE(u);
return res;

View File

@@ -21,14 +21,11 @@
#include <asterisk/image.h>
#include <asterisk/options.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <linux/zaptel.h>
#else
#include <zaptel.h>
#endif /* __linux__ */
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Flash zap trunk application";

View File

@@ -1,90 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Fork CDR application
* Copyright Anthony Minessale anthmct@yahoo.com
* Development of this app Sponsered/Funded by TAAN Softworks Corp
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
static char *tdesc = "Fork The CDR into 2 separate entities.";
static char *app = "ForkCDR";
static char *synopsis =
"Forks the Call Data Record";
static char *descrip =
" ForkCDR(): Causes the Call Data Record to fork an additional\n"
"cdr record starting from the time of the fork call\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static void ast_cdr_clone(struct ast_cdr *cdr) {
struct ast_cdr *newcdr = ast_cdr_alloc();
memcpy(newcdr,cdr,sizeof(struct ast_cdr));
ast_cdr_append(cdr,newcdr);
gettimeofday(&newcdr->start, NULL);
memset(&newcdr->answer, 0, sizeof(newcdr->answer));
ast_cdr_add_flag(cdr,AST_CDR_FLAG_CHILD|AST_CDR_FLAG_LOCKED);
}
static void ast_cdr_fork(struct ast_channel *chan) {
if(chan && chan->cdr) {
ast_cdr_clone(chan->cdr);
}
}
static int forkcdr_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
LOCAL_USER_ADD(u);
ast_cdr_fork(chan);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, forkcdr_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -3,9 +3,9 @@
*
* Execute arbitrary system commands
*
* Copyright (C) 1999-2005, Digium
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -24,6 +24,9 @@
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Get ADSI CPE ID";
static char *app = "GetCPEID";
@@ -31,9 +34,9 @@ static char *app = "GetCPEID";
static char *synopsis = "Get ADSI CPE ID";
static char *descrip =
" GetCPEID: Obtains and displays ADSI CPE ID and other information in order\n"
"to properly setup zapata.conf for on-hook operations.\n"
"Returns -1 on hangup only.\n";
" GetCPEID: Obtains and displays CPE ID and other information in order to\n"
"properly setup zapata.conf for on-hook operations. Returns -1 on hanup\n"
"only.";
STANDARD_LOCAL_USER;
@@ -67,9 +70,9 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
stuff[2] = data[2];
stuff[3] = data[3];
memset(data, 0, sizeof(data));
strncpy(stuff[0], "** CPE Info **", sizeof(data[0]) - 1);
strncpy(stuff[1], "Identifying CPE...", sizeof(data[1]) - 1);
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
strcpy(stuff[0], "** CPE Info **");
strcpy(stuff[1], "Identifying CPE...");
strcpy(stuff[2], "Please wait...");
res = adsi_load_session(chan, NULL, 0, 1);
if (res > 0) {
cpeid_setstatus(chan, stuff, 0);
@@ -80,8 +83,8 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
}
if (res > -1) {
strncpy(stuff[1], "Measuring CPE...", sizeof(data[1]) - 1);
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
strcpy(stuff[1], "Measuring CPE...");
strcpy(stuff[2], "Please wait...");
cpeid_setstatus(chan, stuff, 0);
res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
if (res > -1) {
@@ -92,14 +95,14 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
}
if (res > -1) {
if (gotcpeid)
snprintf(stuff[1], sizeof(data[1]), "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
sprintf(stuff[1], "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
else
strncpy(stuff[1], "CPEID Unknown", sizeof(data[1]) - 1);
strcpy(stuff[1], "CPEID Unknown");
if (gotgeometry)
snprintf(stuff[2], sizeof(data[2]), "Geom: %dx%d, %d buttons", width, height, buttons);
sprintf(stuff[2], "Geom: %dx%d, %d buttons", width, height, buttons);
else
strncpy(stuff[2], "Geometry unknown", sizeof(data[2]) - 1);
strncpy(stuff[3], "Press # to exit", sizeof(data[3]) - 1);
strcpy(stuff[2], "Geometry unknown");
strcpy(stuff[3], "Press # to exit");
cpeid_setstatus(chan, stuff, 1);
for(;;) {
res = ast_waitfordigit(chan, 1000);

View File

@@ -1,224 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Group Manipulation Applications
*
* Copyright (c) 2004 Digium
*
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/utils.h>
static char *tdesc = "Group Management Routines";
static char *app_group_count = "GetGroupCount";
static char *app_group_set = "SetGroup";
static char *app_group_check = "CheckGroup";
static char *group_count_synopsis = "GetGroupCount([groupname][@category])";
static char *group_set_synopsis = "SetGroup(groupname[@category])";
static char *group_check_synopsis = "CheckGroup(max[@category])";
static char *group_count_descrip =
"GetGroupCount([group][@category])\n"
" Calculates the group count for the specified group, or uses\n"
"the current channel's group if not specifed (and non-empty).\n"
"Stores result in GROUPCOUNT. Always returns 0.\n";
static char *group_set_descrip =
"SetGroup(group)\n"
" Sets the channel group to the specified value. Equivalent to\n"
"SetVar(GROUP=group). Always returns 0.\n";
static char *group_check_descrip =
"CheckGroup(max)\n"
" Checks that the current number of total channels in the\n"
"current channel's group does not exceed 'max'. If the number\n"
"does not exceed 'max', we continue to the next step. If the\n"
"number does in fact exceed max, if priority n+101 exists, then\n"
"execution continues at that step, otherwise -1 is returned.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define DEFAULT_CATEGORY "GROUP"
static int group_get_count(char *group, char *category)
{
struct ast_channel *chan;
int count = 0;
char *test;
if (group && !ast_strlen_zero(group)) {
chan = ast_channel_walk_locked(NULL);
while(chan) {
test = pbx_builtin_getvar_helper(chan, category);
if (test && !strcasecmp(test, group))
count++;
ast_mutex_unlock(&chan->lock);
chan = ast_channel_walk_locked(chan);
}
}
return count;
}
static int group_count_exec(struct ast_channel *chan, void *data)
{
int res=0;
int count;
struct localuser *u;
char *group=NULL;
char *cat = NULL;
char ret[80]="";
char tmp[256]="";
LOCAL_USER_ADD(u);
/* Check and parse arguments */
if (data && !ast_strlen_zero(data)) {
strncpy(tmp, data, sizeof(tmp) - 1);
group = tmp;
cat = strchr(tmp, '@');
if (cat) {
*cat = '\0';
cat++;
}
}
if (cat)
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
else
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
if (!group || ast_strlen_zero(group)) {
group = pbx_builtin_getvar_helper(chan, ret);
}
count = group_get_count(group, ret);
snprintf(ret, sizeof(ret), "%d", count);
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
LOCAL_USER_REMOVE(u);
return res;
}
static int group_set_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char ret[80] = "";
char tmp[256] = "";
char *cat=NULL, *group=NULL;
LOCAL_USER_ADD(u);
/* Check and parse arguments */
if (data && !ast_strlen_zero(data)) {
strncpy(tmp, data, sizeof(tmp) - 1);
group = tmp;
cat = strchr(tmp, '@');
if (cat) {
*cat = '\0';
cat++;
}
}
if (cat)
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
else
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
if (group && !ast_strlen_zero(group)) {
pbx_builtin_setvar_helper(chan, ret, group);
} else
ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n");
LOCAL_USER_REMOVE(u);
return res;
}
static int group_check_exec(struct ast_channel *chan, void *data)
{
int res=0;
int max, count;
struct localuser *u;
char ret[80] = "";
char tmp[256] = "";
char *cat, *group;
LOCAL_USER_ADD(u);
if (data && !ast_strlen_zero(data)) {
strncpy(tmp, data, sizeof(tmp) - 1);
group = tmp;
cat = strchr(tmp, '@');
if (cat) {
*cat = '\0';
cat++;
}
if ((sscanf((char *)tmp, "%i", &max) == 1) && (max > -1)) {
if (cat)
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
else
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
count = group_get_count(pbx_builtin_getvar_helper(chan, ret), ret);
if (count > max) {
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
else
res = -1;
}
} else
ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
} else
ast_log(LOG_WARNING, "CheckGroup requires an argument(max)\n");
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
STANDARD_HANGUP_LOCALUSERS;
res = ast_unregister_application(app_group_count);
res |= ast_unregister_application(app_group_set);
res |= ast_unregister_application(app_group_check);
return res;
}
int load_module(void)
{
int res;
res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip);
res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip);
res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,11 +1,8 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* HasVoicemail application
* Changes Copyright (c) 2004 Todd Freeman <freeman@andrews.edu>
*
* 95% based on HasNewVoicemail by:
*
* HasNewVoicemail application
*
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
@@ -37,71 +34,56 @@
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/lock.h>
#include <asterisk/utils.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <pthread.h>
#include "../astconf.h"
static char *tdesc = "Indicator for whether a voice mailbox has messages in a given folder.";
static char *app_hasvoicemail = "HasVoicemail";
static char *hasvoicemail_synopsis = "Conditionally branches to priority + 101";
static char *hasvoicemail_descrip =
"HasVoicemail(vmbox[@context][:folder][|varname])\n"
" Branches to priority + 101, if there is voicemail in folder indicated."
" Optionally sets <varname> to the number of messages in that folder."
" Assumes folder of INBOX if not specified.\n";
static char *tdesc = "Indicator for whether a voice mailbox has new messages.";
static char *app_hasnewvoicemail = "HasNewVoicemail";
static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101";
static char *hasnewvoicemail_descrip =
"HasNewVoicemail(vmbox[@context][|varname])\n"
" Branches to priority + 101, if there is voicemail in folder INBOX."
" Optionally sets <varname> to the number of messages in that folder.\n";
" Branches to priority + 101, if there is new voicemail"
" Optionally sets <varname> to the number of new messages.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int hasvoicemail_exec(struct ast_channel *chan, void *data)
static int hasnewvoicemail_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char vmpath[256], *temps, *input, *varname = NULL, *vmbox, *vmfolder = "INBOX", *context = "default";
char vmpath[256], *input, *varname = NULL, *vmbox, *context = "default";
DIR *vmdir;
struct dirent *vment;
int vmcount = 0;
if (!data) {
ast_log(LOG_WARNING, "HasVoicemail requires an argument (vm-box[@context][:folder]|varname)\n");
ast_log(LOG_WARNING, "HasNewVoicemail requires an argument (vm-box[@context]|varname)\n");
return -1;
}
LOCAL_USER_ADD(u);
input = ast_strdupa((char *)data);
if (input) {
temps = input;
if ((temps = strsep(&input, "|"))) {
if (input && !ast_strlen_zero(input))
varname = input;
input = temps;
}
if ((temps = strsep(&input, ":"))) {
if (input && !ast_strlen_zero(input))
vmfolder = input;
input = temps;
}
if ((vmbox = strsep(&input, "@")))
if (input && !ast_strlen_zero(input))
context = input;
if (!vmbox)
if ((vmbox = strsep(&input,"|")))
varname = input;
else
vmbox = input;
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR, context, vmbox, vmfolder);
if (index(vmbox,'@')) {
context = vmbox;
vmbox = strsep(&context,"@");
}
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, vmbox);
if (!(vmdir = opendir(vmpath))) {
ast_log(LOG_NOTICE, "Voice mailbox %s at %s does not exist\n", vmbox, vmpath);
} else {
@@ -115,7 +97,7 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
/* Set the count in the channel variable */
if (varname) {
char tmp[12];
snprintf(tmp, sizeof(tmp), "%d", vmcount);
snprintf(tmp, sizeof(tmp) - 1, "%d", vmcount);
pbx_builtin_setvar_helper(chan, varname, tmp);
}
@@ -136,19 +118,13 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
int unload_module(void)
{
int res;
STANDARD_HANGUP_LOCALUSERS;
res = ast_unregister_application(app_hasvoicemail);
res |= ast_unregister_application(app_hasnewvoicemail);
return res;
return ast_unregister_application(app_hasnewvoicemail);
}
int load_module(void)
{
int res;
res = ast_register_application(app_hasvoicemail, hasvoicemail_exec, hasvoicemail_synopsis, hasvoicemail_descrip);
res |= ast_register_application(app_hasnewvoicemail, hasvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
return res;
return ast_register_application(app_hasnewvoicemail, hasnewvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
}
char *description(void)

View File

@@ -1,196 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/frame.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
#include "../astconf.h"
#define ICES "/usr/bin/ices"
#define LOCAL_ICES "/usr/local/bin/ices"
static char *tdesc = "Encode and Stream via icecast and ices";
static char *app = "ICES";
static char *synopsis = "Encode and stream using 'ices'";
static char *descrip =
" ICES(config.xml) Streams to an icecast server using ices\n"
"(available separately). A configuration file must be supplied\n"
"for ices (see examples/asterisk-ices.conf). Returns -1 on\n"
"hangup or 0 otherwise.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int icesencode(char *filename, int fd)
{
int res;
int x;
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res)
return res;
dup2(fd, STDIN_FILENO);
for (x=STDERR_FILENO + 1;x<256;x++) {
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
close(x);
}
/* Most commonly installed in /usr/local/bin */
execl(ICES, "ices", filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(LOCAL_ICES, "ices", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("ices", "ices", filename, (char *)NULL);
ast_log(LOG_WARNING, "Execute of ices failed\n");
return -1;
}
static int ices_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
int flags;
int oreadformat;
struct timeval last;
struct ast_frame *f;
char filename[256]="";
char *c;
last.tv_usec = 0;
last.tv_sec = 0;
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
return -1;
}
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
}
flags = fcntl(fds[1], F_GETFL);
fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
LOCAL_USER_ADD(u);
ast_stopstream(chan);
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (res) {
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Answer failed!\n");
return -1;
}
oreadformat = chan->readformat;
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
return -1;
}
if (((char *)data)[0] == '/')
strncpy(filename, (char *)data, sizeof(filename) - 1);
else
snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
/* Placeholder for options */
c = strchr(filename, '|');
if (c)
*c = '\0';
res = icesencode(filename, fds[0]);
close(fds[0]);
if (res >= 0) {
pid = res;
for (;;) {
/* Wait for audio, and stream */
ms = ast_waitfor(chan, -1);
if (ms < 0) {
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
f = ast_read(chan);
if (!f) {
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_VOICE) {
res = write(fds[1], f->data, f->datalen);
if (res < 0) {
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
res = -1;
break;
}
}
}
ast_frfree(f);
}
}
close(fds[1]);
LOCAL_USER_REMOVE(u);
if (pid > -1)
kill(pid, SIGKILL);
if (!res && oreadformat)
ast_set_read_format(chan, oreadformat);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, ices_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -21,6 +21,7 @@
#include <asterisk/image.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Image Transmission Application";

View File

@@ -24,16 +24,16 @@
#include <sys/ioctl.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <netinet/in.h>
#if defined(__linux__)
#ifdef __linux__
#include <linux/soundcard.h>
#elif defined(__FreeBSD__)
#include <sys/soundcard.h>
#include <machine/soundcard.h>
#else
#include <soundcard.h>
#endif
#include <netinet/in.h>
#ifdef __OpenBSD__
#define DEV_DSP "/dev/audio"
@@ -58,7 +58,7 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
AST_MUTEX_DEFINE_STATIC(sound_lock);
static ast_mutex_t sound_lock = AST_MUTEX_INITIALIZER;
static int sound = -1;
static int write_audio(short *data, int len)

View File

@@ -24,6 +24,7 @@
#include <asterisk/astdb.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Look up Caller*ID name/number from blacklist database";

View File

@@ -24,6 +24,7 @@
#include <asterisk/astdb.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Look up CallerID Name from local database";

View File

@@ -18,13 +18,13 @@
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_ARGS 80
static char *tdesc = "Extension Macros";
@@ -73,14 +73,14 @@ static int macro_exec(struct ast_channel *chan, void *data)
char *save_macro_priority;
char *save_macro_offset;
if (!data || ast_strlen_zero(data)) {
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "Invalid Macro incantation\n");
return 0;
}
strncpy(tmp, data, sizeof(tmp) - 1);
rest = tmp;
macro = strsep(&rest, "|");
if (!macro || ast_strlen_zero(macro)) {
if (!macro || !strlen(macro)) {
ast_log(LOG_WARNING, "Invalid macro name specified\n");
return 0;
}
@@ -96,7 +96,7 @@ static int macro_exec(struct ast_channel *chan, void *data)
oldpriority = chan->priority;
strncpy(oldexten, chan->exten, sizeof(oldexten) - 1);
strncpy(oldcontext, chan->context, sizeof(oldcontext) - 1);
if (ast_strlen_zero(chan->macrocontext)) {
if (!strlen(chan->macrocontext)) {
strncpy(chan->macrocontext, chan->context, sizeof(chan->macrocontext) - 1);
strncpy(chan->macroexten, chan->exten, sizeof(chan->macroexten) - 1);
chan->macropriority = chan->priority;
@@ -122,9 +122,8 @@ static int macro_exec(struct ast_channel *chan, void *data)
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
/* Setup environment for new run */
chan->exten[0] = 's';
chan->exten[1] = '\0';
strncpy(chan->context, fullmacro, sizeof(chan->context) - 1);
strcpy(chan->exten, "s");
strncpy(chan->context, fullmacro, sizeof(chan->context));
chan->priority = 1;
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
@@ -140,8 +139,7 @@ static int macro_exec(struct ast_channel *chan, void *data)
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid))) {
/* Something bad happened, or a hangup has been requested. */
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
(res == '*') || (res == '#')) {
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F'))) {
/* Just return result as to the previous application as if it had been dialed */
ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
break;
@@ -195,8 +193,8 @@ out:
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
if (save_macro_priority) free(save_macro_priority);
if (setmacrocontext) {
chan->macrocontext[0] = '\0';
chan->macroexten[0] = '\0';
strcpy(chan->macrocontext, "");
strcpy(chan->macroexten, "");
chan->macropriority = 0;
}
@@ -204,7 +202,7 @@ out:
/* If we're leaving the macro normally, restore original information */
chan->priority = oldpriority;
strncpy(chan->context, oldcontext, sizeof(chan->context) - 1);
if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
if (!chan->_softhangup) {
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1);
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,8 @@
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
static char *app = "Milliwatt";
@@ -62,7 +64,7 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
if (len > sizeof(buf))
{
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)sizeof(buf),len);
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",sizeof(buf),len);
len = sizeof(buf);
}
waste[0] = 0; /* make compiler happy */
@@ -74,8 +76,6 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
wf.datalen = len;
wf.samples = wf.datalen;
wf.src = "app_milliwatt";
wf.delivery.tv_sec = 0;
wf.delivery.tv_usec = 0;
/* create a buffer containing the digital milliwatt pattern */
for(i = 0; i < len; i++)
{

View File

@@ -3,9 +3,9 @@
*
* Silly application to play an MP3 file -- uses mpg123
*
* Copyright (C) 1999-2004, Digium, Inc.
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/time.h>
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
@@ -60,35 +61,36 @@ static int mp3play(char *filename, int fd)
close(x);
}
/* Execute mpg123, but buffer if it's a net connection */
if (!strncasecmp(filename, "http://", 7)) {
if (strncmp(filename, "http://", 7)) {
/* Most commonly installed in /usr/local/bin */
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
}
else {
/* Most commonly installed in /usr/local/bin */
execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
execl(MPG_123, "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
execlp("mpg123", "mpg123", "-q", "-s", "--mono", "-r", "8000", filename, (char *)NULL);
}
ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
return -1;
}
static int timed_read(int fd, void *data, int datalen, int timeout)
static int timed_read(int fd, void *data, int datalen)
{
int res;
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
res = poll(fds, 1, timeout);
fd_set fds;
struct timeval tv = { 2, 0 }; /* Wait no more than 2 seconds */
FD_ZERO(&fds);
FD_SET(fd, &fds);
res = ast_select(fd + 1, &fds, NULL, NULL, &tv);
if (res < 1) {
ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
return -1;
}
return read(fd, data, datalen);
@@ -103,14 +105,15 @@ static int mp3_exec(struct ast_channel *chan, void *data)
int ms = -1;
int pid = -1;
int owriteformat;
int timeout = 2000;
struct timeval now, next;
struct timeval last;
struct ast_frame *f;
struct myframe {
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
short frdata[160];
} myf;
last.tv_usec = 0;
last.tv_sec = 0;
if (!data) {
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
return -1;
@@ -129,36 +132,36 @@ static int mp3_exec(struct ast_channel *chan, void *data)
return -1;
}
gettimeofday(&now, NULL);
res = mp3play((char *)data, fds[1]);
if (!strncasecmp((char *)data, "http://", 7)) {
timeout = 10000;
}
/* Wait 1000 ms first */
next = now;
next.tv_sec += 1;
ms = 1000;
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
for (;;) {
gettimeofday(&now, NULL);
ms = (next.tv_sec - now.tv_sec) * 1000;
ms += (next.tv_usec - now.tv_usec) / 1000;
#if 0
printf("ms: %d\n", ms);
#endif
if (ms <= 0) {
#if 0
{
static struct timeval last;
struct timeval tv;
gettimeofday(&tv, NULL);
printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
last = tv;
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
if (ms) {
f = ast_read(chan);
if (!f) {
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
#endif
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
if (f->frametype == AST_FRAME_DTMF) {
ast_log(LOG_DEBUG, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
}
ast_frfree(f);
} else {
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
if (res > 0) {
myf.f.frametype = AST_FRAME_VOICE;
myf.f.subclass = AST_FORMAT_SLINEAR;
@@ -167,8 +170,6 @@ static int mp3_exec(struct ast_channel *chan, void *data)
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
myf.f.delivery.tv_sec = 0;
myf.f.delivery.tv_usec = 0;
myf.f.data = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
@@ -179,36 +180,7 @@ static int mp3_exec(struct ast_channel *chan, void *data)
res = 0;
break;
}
next.tv_usec += res / 2 * 125;
if (next.tv_usec >= 1000000) {
next.tv_usec -= 1000000;
next.tv_sec++;
}
#if 0
printf("Next: %d\n", ms);
#endif
} else {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
if (ms) {
f = ast_read(chan);
if (!f) {
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_log(LOG_DEBUG, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
}
ast_frfree(f);
}
ms = res / 16;
}
}
}

View File

@@ -1,229 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Silly application to play an NBScat file -- uses nbscat8k
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/frame.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
#define NBSCAT "/usr/bin/nbscat8k"
static char *tdesc = "Silly NBS Stream Application";
static char *app = "NBScat";
static char *synopsis = "Play an NBS local stream";
static char *descrip =
" NBScat: Executes nbscat to listen to the local NBS stream.\n"
"Returns -1 on\n hangup or 0 otherwise. User can exit by \n"
"pressing any key\n.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int NBScatplay(int fd)
{
int res;
int x;
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res)
return res;
dup2(fd, STDOUT_FILENO);
for (x=0;x<256;x++) {
if (x != STDOUT_FILENO)
close(x);
}
/* Most commonly installed in /usr/local/bin */
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
return -1;
}
static int timed_read(int fd, void *data, int datalen)
{
int res;
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
res = poll(fds, 1, 2000);
if (res < 1) {
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
return -1;
}
return read(fd, data, datalen);
}
static int NBScat_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
int owriteformat;
struct timeval now, next;
struct ast_frame *f;
struct myframe {
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
short frdata[160];
} myf;
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
ast_log(LOG_WARNING, "Unable to create socketpair\n");
return -1;
}
LOCAL_USER_ADD(u);
ast_stopstream(chan);
owriteformat = chan->writeformat;
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
return -1;
}
res = NBScatplay(fds[1]);
/* Wait 1000 ms first */
next = now;
next.tv_sec += 1;
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
for (;;) {
gettimeofday(&now, NULL);
ms = (next.tv_sec - now.tv_sec) * 1000;
ms += (next.tv_usec - now.tv_usec) / 1000;
#if 0
printf("ms: %d\n", ms);
#endif
if (ms <= 0) {
#if 0
{
static struct timeval last;
struct timeval tv;
gettimeofday(&tv, NULL);
printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
last = tv;
}
#endif
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
if (res > 0) {
myf.f.frametype = AST_FRAME_VOICE;
myf.f.subclass = AST_FORMAT_SLINEAR;
myf.f.datalen = res;
myf.f.samples = res / 2;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
myf.f.delivery.tv_sec = 0;
myf.f.delivery.tv_usec = 0;
myf.f.data = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
}
} else {
ast_log(LOG_DEBUG, "No more mp3\n");
res = 0;
break;
}
next.tv_usec += res / 2 * 125;
if (next.tv_usec >= 1000000) {
next.tv_usec -= 1000000;
next.tv_sec++;
}
#if 0
printf("Next: %d\n", ms);
#endif
} else {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
if (ms) {
f = ast_read(chan);
if (!f) {
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_log(LOG_DEBUG, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
}
ast_frfree(f);
}
}
}
}
close(fds[0]);
close(fds[1]);
LOCAL_USER_REMOVE(u);
if (pid > -1)
kill(pid, SIGKILL);
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, NBScat_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,277 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Time of day - Report the time of day
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/options.h>
#include <asterisk/config.h>
#include <asterisk/module.h>
#include <asterisk/utils.h>
#include <asterisk/causes.h>
#include <asterisk/astosp.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
static char *tdesc = "OSP Lookup";
static char *app = "OSPLookup";
static char *app2 = "OSPNext";
static char *app3 = "OSPFinish";
static char *synopsis = "Lookup number in OSP";
static char *synopsis2 = "Lookup next OSP entry";
static char *synopsis3 = "Record OSP entry";
static char *descrip =
" OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
"the variables, where 'n' is the number of the result beginning with 1:\n"
" ${OSPTECH}: The technology to use for the call\n"
" ${OSPDEST}: The destination to use for the call\n"
" ${OSPTOKEN}: The actual OSP token as a string\n"
" ${OSPHANDLE}: The OSP Handle for anything remaining\n"
" ${OSPRESULTS}: The number of OSP results total remaining\n"
"\n"
"If the lookup was *not* successful and there exists a priority n + 101,\n"
"then that priority will be taken next.\n" ;
static char *descrip2 =
" OSPNext: Looks up the next OSP Destination for ${OSPHANDLE}\n"
"See OSPLookup for more information\n"
"\n"
"If the lookup was *not* successful and there exists a priority n + 101,\n"
"then that priority will be taken next.\n" ;
static char *descrip3 =
" OSPFinish(status): Records call state for ${OSPHANDLE}, according to\n"
"status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or NOCHANAVAIL\n"
"or coincidentally, just what the Dial application stores in its ${DIALSTATUS}\n"
"\n"
"If the finishing was *not* successful and there exists a priority n + 101,\n"
"then that priority will be taken next.\n" ;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int str2cause(char *cause)
{
if (!strcasecmp(cause, "BUSY"))
return AST_CAUSE_BUSY;
if (!strcasecmp(cause, "CONGESTION"))
return AST_CAUSE_CONGESTION;
if (!strcasecmp(cause, "ANSWER"))
return AST_CAUSE_NORMAL;
if (!strcasecmp(cause, "CANCEL"))
return AST_CAUSE_NORMAL;
if (!strcasecmp(cause, "NOANSWER"))
return AST_CAUSE_NOANSWER;
if (!strcasecmp(cause, "NOCHANAVAIL"))
return AST_CAUSE_CONGESTION;
ast_log(LOG_WARNING, "Unknown cause '%s', using NORMAL\n", cause);
return AST_CAUSE_NORMAL;
}
static int osplookup_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *temp;
char *provider, *opts=NULL;
struct ast_osp_result result;
if (!data || ast_strlen_zero(data) || !(temp = ast_strdupa(data))) {
ast_log(LOG_WARNING, "OSPLookup requires an argument (extension)\n");
return -1;
}
provider = strchr(temp, '|');
if (provider) {
*provider = '\0';
provider++;
opts = strchr(provider, '|');
if (opts) {
*opts = '\0';
opts++;
}
}
LOCAL_USER_ADD(u);
ast_log(LOG_DEBUG, "Whoo hoo, looking up OSP on '%s' via '%s'\n", temp, provider ? provider : "<default>");
if ((res = ast_osp_lookup(chan, provider, temp, chan->callerid, &result)) > 0) {
char tmp[80];
snprintf(tmp, sizeof(tmp), "%d", result.handle);
pbx_builtin_setvar_helper(chan, "OSPHANDLE", tmp);
pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
pbx_builtin_setvar_helper(chan, "OSPTOKEN", result.token);
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
pbx_builtin_setvar_helper(chan, "OSPRESULTS", tmp);
} else {
if (!res)
ast_log(LOG_NOTICE, "OSP Lookup failed for '%s' (provider '%s')\n", temp, provider ? provider : "<default>");
else
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Lookup for '%s' (provider '%s')!\n", chan->name, temp, provider ? provider : "<default>" );
}
if (!res) {
/* Look for a "busy" place */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
} else if (res > 0)
res = 0;
LOCAL_USER_REMOVE(u);
return res;
}
static int ospnext_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *temp;
int cause;
struct ast_osp_result result;
if (!data || ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "OSPNext should have an argument (cause)\n");
}
LOCAL_USER_ADD(u);
cause = str2cause((char *)data);
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
result.handle = -1;
if (temp && strlen(temp) && (sscanf(temp, "%i", &result.handle) == 1) && (result.handle > -1)) {
if ((res = ast_osp_next(&result, cause)) > 0) {
char tmp[80];
snprintf(tmp, sizeof(tmp), "%d", result.handle);
pbx_builtin_setvar_helper(chan, "OSPHANDLE", tmp);
pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
pbx_builtin_setvar_helper(chan, "OSPTOKEN", result.token);
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
pbx_builtin_setvar_helper(chan, "OSPRESULTS", tmp);
}
} else {
if (!res) {
if (result.handle < 0)
ast_log(LOG_NOTICE, "OSP Lookup Next failed for handle '%d'\n", result.handle);
else
ast_log(LOG_DEBUG, "No OSP handle specified\n");
} else
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Next!\n", chan->name);
}
if (!res) {
/* Look for a "busy" place */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
} else if (res > 0)
res = 0;
LOCAL_USER_REMOVE(u);
return res;
}
static int ospfinished_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *temp;
int cause;
time_t start=0, duration=0;
struct ast_osp_result result;
if (!data || ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "OSPFinish should have an argument (cause)\n");
}
if (chan->cdr) {
start = chan->cdr->answer.tv_sec;
if (start)
duration = time(NULL) - start;
else
duration = 0;
} else
ast_log(LOG_WARNING, "OSPFinish called on channel '%s' with no CDR!\n", chan->name);
LOCAL_USER_ADD(u);
cause = str2cause((char *)data);
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
result.handle = -1;
if (temp && strlen(temp) && (sscanf(temp, "%i", &result.handle) == 1) && (result.handle > -1)) {
if (!ast_osp_terminate(result.handle, cause, start, duration)) {
pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
res = 1;
}
} else {
if (!res) {
if (result.handle > -1)
ast_log(LOG_NOTICE, "OSP Finish failed for handle '%d'\n", result.handle);
else
ast_log(LOG_DEBUG, "No OSP handle specified\n");
} else
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Terminate!\n", chan->name);
}
if (!res) {
/* Look for a "busy" place */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
} else if (res > 0)
res = 0;
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
STANDARD_HANGUP_LOCALUSERS;
res = ast_unregister_application(app3);
res |= ast_unregister_application(app2);
res |= ast_unregister_application(app);
return res;
}
int load_module(void)
{
int res;
res = ast_register_application(app, osplookup_exec, synopsis, descrip);
if (res)
return(res);
res = ast_register_application(app2, ospnext_exec, synopsis2, descrip2);
if (res)
return(res);
res = ast_register_application(app3, ospfinished_exec, synopsis3, descrip3);
if (res)
return(res);
return(0);
}
int reload(void)
{
return 0;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -21,17 +21,18 @@
#include <asterisk/channel_pvt.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/features.h>
#include <asterisk/parking.h>
#include <asterisk/options.h>
#include <asterisk/logger.h>
#include <asterisk/say.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Call Parking and Announce Application";
static char *app = "ParkAndAnnounce";
@@ -41,7 +42,7 @@ static char *synopsis = "Park and Announce";
static char *descrip =
" ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
"Park a call into the parkinglot and announce the call over the console.\n"
"announce template: colon separated list of files to announce, the word PARKED\n"
"announce template: colon seperated list of files to announce, the word PARKED\n"
" will be replaced by a say_digits of the ext the call is parked in\n"
"timeout: time in seconds before the call returns into the return context.\n"
"dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
@@ -54,171 +55,170 @@ LOCAL_USER_DECL;
static int parkandannounce_exec(struct ast_channel *chan, void *data)
{
int res=0;
char *return_context;
int l, lot, timeout = 0, dres;
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
char *template, *tpl_working, *tpl_current;
char *tmp[100];
int looptemp=0,i=0;
char *s,*orig_s;
int res=0;
char *return_context;
int l, lot, timeout, dres;
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
char *template, *tpl_working, *tpl_current;
char *tmp[100];
int looptemp=0,i=0;
char *s,*orig_s;
struct ast_channel *dchan;
int outstate;
struct ast_channel *dchan;
int outstate;
struct localuser *u;
if(!data || (data && !strlen(data))) {
ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
return -1;
}
struct localuser *u;
if (!data) {
ast_log(LOG_WARNING, "Park requires an argument (parkinglot)\n");
return -1;
}
l=strlen(data)+2;
orig_s=malloc(l);
if(!orig_s) {
ast_log(LOG_WARNING, "Out of memory\n");
return -1;
}
s=orig_s;
strncpy(s,data,l);
l=strlen(data)+2;
orig_s=malloc(l);
s=orig_s;
strncpy(s,data,l);
template=strsep(&s,"|");
if(! template) {
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
free(orig_s);
return -1;
}
template=strsep(&s,"|");
if (! template) {
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
free(orig_s);
return -1;
}
if(s) {
timeout = atoi(strsep(&s, "|"));
timeout *= 1000;
}
dial=strsep(&s, "|");
if(!dial) {
ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
free(orig_s);
return -1;
} else {
dialtech=strsep(&dial, "/");
dialstr=dial;
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
}
timeout = atoi(strsep(&s, "|"));
timeout *= 1000;
return_context = s;
dial=strsep(&s, "|");
if (! dial) {
ast_log(LOG_WARNING, "PARK: A dial resouce must be specified i.e: Console/dsp or Zap/g1/5551212\n");
free(orig_s);
return -1;
}
else {
dialtech=strsep(&dial, "/");
dialstr=dial;
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
}
return_context = s;
if(return_context != NULL) {
/* set the return context. Code borrowed from the Goto builtin */
if (return_context != NULL) {
/* set the return context. Code borrowed from the Goto builtin */
working = return_context;
context = strsep(&working, "|");
exten = strsep(&working, "|");
if(!exten) {
/* Only a priority in this one */
priority = context;
exten = NULL;
context = NULL;
} else {
priority = strsep(&working, "|");
if(!priority) {
/* Only an extension and priority in this one */
priority = exten;
exten = context;
context = NULL;
}
}
if(atoi(priority) < 0) {
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
free(orig_s);
return -1;
}
/* At this point we have a priority and maybe an extension and a context */
chan->priority = atoi(priority);
if(exten && strcasecmp(exten, "BYEXTENSION"))
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
if(context)
strncpy(chan->context, context, sizeof(chan->context)-1);
} else { /* increment the priority by default*/
chan->priority++;
}
working = return_context;
context = strsep(&working, "|");
exten = strsep(&working, "|");
if (!exten) {
/* Only a priority in this one */
priority = context;
exten = NULL;
context = NULL;
} else {
priority = strsep(&working, "|");
if (!priority) {
/* Only an extension and priority in this one */
priority = exten;
exten = context;
context = NULL;
}
}
if (atoi(priority) < 0) {
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
free(orig_s);
return -1;
}
/* At this point we have a priority and maybe an extension and a context */
chan->priority = atoi(priority);
if (exten && strcasecmp(exten, "BYEXTENSION"))
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
if (context)
strncpy(chan->context, context, sizeof(chan->context)-1);
}
else { /* increment the priority by default*/
chan->priority++;
}
if(option_verbose > 2) {
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->callerid);
if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
}
}
if (option_verbose > 2) {
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->callerid);
if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
}
}
LOCAL_USER_ADD(u);
LOCAL_USER_ADD(u);
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
ast_masq_park_call(chan, NULL, timeout, &lot);
ast_masq_park_call(chan, NULL, timeout, &lot);
res=-1;
res=-1;
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
/* Now place the call to the extention */
/* Now place the call to the extention */
dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->callerid);
dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->callerid);
if(dchan) {
if(dchan->_state == AST_STATE_UP) {
if(option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
} else {
if(option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
ast_hangup(dchan);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
} else {
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
if (dchan) {
if (dchan->_state == AST_STATE_UP) {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
} else {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
ast_hangup(dchan);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
}
else {
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
ast_stopstream(dchan);
ast_stopstream(dchan);
/* now we have the call placed and are ready to play stuff to it */
/* now we have the call placed and are ready to play stuff to it */
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
tpl_working = template;
tpl_current=strsep(&tpl_working, ":");
tpl_working = template;
tpl_current=strsep(&tpl_working, ":");
while(tpl_current && looptemp < sizeof(tmp)) {
tmp[looptemp]=tpl_current;
looptemp++;
tpl_current=strsep(&tpl_working,":");
}
while ( tpl_current && looptemp < sizeof(tmp)) {
tmp[looptemp]=tpl_current;
looptemp++;
tpl_current=strsep(&tpl_working,":");
}
for(i=0; i<looptemp; i++) {
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
if(!strcmp(tmp[i], "PARKED")) {
ast_say_digits(dchan, lot, "", dchan->language);
} else {
dres = ast_streamfile(dchan, tmp[i], dchan->language);
if(!dres) {
dres = ast_waitstream(dchan, "");
} else {
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
dres = 0;
}
}
}
for(i=0; i<looptemp; i++) {
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
if (!strcmp(tmp[i], "PARKED")) {
ast_say_digits(dchan, lot, "", dchan->language);
}
else {
dres = ast_streamfile(dchan, tmp[i], dchan->language);
if (!dres)
dres = ast_waitstream(dchan, "");
else {
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
dres = 0;
}
}
}
ast_stopstream(dchan);
ast_hangup(dchan);
ast_stopstream(dchan);
ast_hangup(dchan);
LOCAL_USER_REMOVE(u);
free(orig_s);
return res;
LOCAL_USER_REMOVE(u);
free(orig_s);
return res;
}
@@ -231,8 +231,8 @@ int unload_module(void)
int load_module(void)
{
/* return ast_register_application(app, park_exec); */
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
/* return ast_register_application(app, park_exec); */
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
}
char *description(void)

View File

@@ -18,9 +18,9 @@
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/utils.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Trivial Playback Application";
@@ -30,14 +30,14 @@ static char *synopsis = "Play a file";
static char *descrip =
" Playback(filename[|option]): Plays back a given filename (do not put\n"
"extension). Options may also be included following a pipe symbol. The 'skip'\n"
"option causes the playback of the message to be skipped if the channel\n"
"is not in the 'up' state (i.e. it hasn't been answered yet. If 'skip' is \n"
"specified, the application will return immediately should the channel not be\n"
"off hook. Otherwise, unless 'noanswer' is specified, the channel channel will\n"
"be answered before the sound is played. Not all channels support playing\n"
"messages while still hook. Returns -1 if the channel was hung up, or if the\n"
"file does not exist. Returns 0 otherwise.\n";
"extension). Options may also be included following a pipe symbol. The only\n"
"defined option at this time is 'skip', which causes the playback of the\n"
"message to be skipped if the channel is not in the 'up' state (i.e. it\n"
"hasn't been answered yet. If 'skip' is specified, the application will\n"
"return immediately should the channel not be off hook. Otherwise, unless\n"
"'noanswer' is specified, the channel channel will be answered before the sound\n"
"is played. Not all channels support playing messages while on hook. Returns -1\n"
"if the channel was hung up, or if the file does not exist. Returns 0 otherwise.\n";
STANDARD_LOCAL_USER;
@@ -52,7 +52,7 @@ static int playback_exec(struct ast_channel *chan, void *data)
int option_skip=0;
int option_noanswer = 0;
char *stringp;
if (!data || ast_strlen_zero((char *)data)) {
if (!data || !strlen((char *)data)) {
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
return -1;
}

View File

@@ -25,6 +25,7 @@
#include <asterisk/config.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#define PRIV_CONFIG "privacy.conf"

View File

@@ -51,7 +51,6 @@
*/
#include <asterisk/lock.h>
#include <asterisk/utils.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
@@ -63,6 +62,7 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
@@ -123,7 +123,7 @@ pthread_attr_t attr;
while((dp = readdir(dirp)) != NULL)
{
if (dp->d_name[0] == '.') continue;
snprintf(fname, sizeof(fname), "%s/%s", qdir, dp->d_name);
sprintf(fname,"%s/%s",qdir,dp->d_name);
if (stat(fname,&mystat) == -1)
{
perror("app_qcall:stat");
@@ -157,7 +157,7 @@ pthread_attr_t attr;
arg = (void *) strdup(fname);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (ast_pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
if (pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
{
perror("qcall: Cannot create thread");
continue;
@@ -172,20 +172,15 @@ pthread_attr_t attr;
/* single thread with one file (request) to dial */
static void *qcall_do(void *arg)
{
char fname[300] = "";
char dialstr[300];
char extstr[300];
char ident[300] = "";
char reqinp[300] = "";
char buf[300];
char clid[300],*tele,*context;
FILE *fp;
int ms = MAXWAITFORANSWER,maxsecs;
struct ast_channel *channel;
time_t t;
char fname[300],dialstr[300],extstr[300],ident[300],reqinp[300],buf[300];
char clid[300],*tele,*context;
FILE *fp;
int ms = MAXWAITFORANSWER,maxsecs;
struct ast_channel *channel;
time_t t;
/* get the filename from the arg */
strncpy(fname,(char *)arg, sizeof(fname) - 1);
strcpy(fname,(char *)arg);
free(arg);
time(&t);
fp = fopen(fname,"r");
@@ -203,11 +198,8 @@ static void *qcall_do(void *arg)
fprintf(stderr,"%s\n",fname);
pthread_exit(NULL);
}
/* default required input for acknowledgement */
reqinp[0] = '1';
reqinp[1] = '\0';
/* default no ident */
ident[0] = '\0'; /* default no ident */
strcpy(reqinp,"1"); /* default required input for acknowledgement */
strcpy(ident, ""); /* default no ident */
if (fscanf(fp,"%s %s %s %d %s %s",dialstr,clid,
extstr,&maxsecs,ident,reqinp) < 4)
{
@@ -316,7 +308,7 @@ static void *qcall_do(void *arg)
ast_verbose(VERBOSE_PREFIX_3 "Qcall got accept, now putting through to %s@%s on %s\n",
extstr,context,channel->name);
if (strlen(ident)) {
strncat(ident,"-ok", sizeof(ident) - strlen(ident) - 1);
strcat(ident,"-ok");
/* if file existant, play it */
if (!ast_streamfile(channel,ident,0))
{
@@ -334,7 +326,7 @@ static void *qcall_do(void *arg)
channel->amaflags = AMAFLAGS;
#endif
#ifdef ACCTCODE
strncpy(channel->accountcode, ACCTCODE, sizeof(chan->accountcode) - 1);
strcpy(channel->accountcode,ACCTCODE);
#else
channel->accountcode[0] = 0;
#endif
@@ -343,10 +335,10 @@ static void *qcall_do(void *arg)
time(&channel->whentohangup);
channel->whentohangup += maxsecs;
}
strncpy(channel->exten, extstr, sizeof(channel->exten) - 1);
strncpy(channel->context, context, sizeof(channel->context) - 1);
strcpy(channel->exten,extstr);
strcpy(channel->context,context);
channel->priority = 1;
if(debug) printf("Caller ID is %s\n", channel->callerid);
printf("Caller ID is %s\n", channel->callerid);
ast_pbx_run(channel);
pthread_exit(NULL);
}
@@ -370,9 +362,9 @@ int unload_module(void)
int load_module(void)
{
snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "qcall");
snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"qcall");
mkdir(qdir,0760);
ast_pthread_create(&qcall_thread,NULL,qcall,NULL);
pthread_create(&qcall_thread,NULL,qcall,NULL);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -42,7 +42,7 @@ static int random_exec(struct ast_channel *chan, void *data)
int res=0;
struct localuser *u;
char *s;
char *s, *ts;
char *exten, *pri, *context;
char *prob;
int probint, priorityint;
@@ -54,7 +54,7 @@ static int random_exec(struct ast_channel *chan, void *data)
LOCAL_USER_ADD(u);
s = ast_strdupa((void *) data);
prob = strsep(&s,":");
prob = strsep(&ts,":");
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
probint = 0;

View File

@@ -20,9 +20,9 @@
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Read Variable Application";
@@ -31,17 +31,9 @@ static char *app = "Read";
static char *synopsis = "Read a variable";
static char *descrip =
" Read(variable[|filename][|maxdigits][|option])\n\n"
"Reads a #-terminated string of digits from the user in to the given variable,\n"
"optionally playing a given filename first.\n"
" maxdigits -- maximum acceptable number of digits. Stops reading after\n"
" maxdigits have been entered (without requiring the user to\n"
" press the '#' key).\n"
" Defaults to 0 - no limit - wait for the user press the '#' key.\n"
" Any value below 0 means the same. Max accepted value is 255.\n"
" option -- may be 'skip' to return immediately if the line is not up,\n"
" or 'noanswer' to read digits even if the line is not up.\n\n"
"Returns -1 on hangup or error and 0 otherwise.\n";
" Read(variable[|filename]): Reads a '#' terminated string of digits from\n"
"the user, optionally playing a given filename first. Returns -1 on hangup or\n"
"error and 0 otherwise.\n";
STANDARD_LOCAL_USER;
@@ -52,64 +44,32 @@ static int read_exec(struct ast_channel *chan, void *data)
int res = 0;
struct localuser *u;
char tmp[256];
char argdata[256] = "";
char *varname;
char tmp2[128]="";
char *filename;
char *stringp;
char *maxdigitstr;
char *options;
int option_skip = 0;
int option_noanswer = 0;
int maxdigits=255;
if (!data || ast_strlen_zero((char *)data)) {
if (!data || !strlen((char *)data)) {
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
return -1;
}
strncpy(argdata, (char *)data, sizeof(argdata)-1);
stringp=argdata;
varname = strsep(&stringp, "|");
strncpy(tmp, (char *)data, sizeof(tmp)-1);
stringp=tmp;
strsep(&stringp, "|");
filename = strsep(&stringp, "|");
maxdigitstr = strsep(&stringp,"|");
options = strsep(&stringp, "|");
if (options && !strcasecmp(options, "skip"))
option_skip = 1;
if (options && !strcasecmp(options, "noanswer"))
option_noanswer = 1;
if (!(filename) || ast_strlen_zero(filename))
filename = NULL;
if (maxdigitstr) {
maxdigits = atoi(maxdigitstr);
if ((maxdigits<1) || (maxdigits>255)) {
maxdigits = 255;
} else
ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %i digits.\n", maxdigits);
}
if (!(varname) || ast_strlen_zero(varname)) {
if (!strlen(tmp)) {
ast_log(LOG_WARNING, "Read requires an variable name\n");
return -1;
}
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
pbx_builtin_setvar_helper(chan, varname, "\0");
LOCAL_USER_REMOVE(u);
return 0;
} else if (!option_noanswer) {
/* Otherwise answer unless we're supposed to read while on-hook */
res = ast_answer(chan);
}
/* Answer if the line isn't up. */
res = ast_answer(chan);
}
if (!res) {
ast_stopstream(chan);
res = ast_app_getdata(chan, filename, tmp, maxdigits, 0);
if (res > -1) {
pbx_builtin_setvar_helper(chan, varname, tmp);
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
res = 0;
} else {
ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
}
res = ast_app_getdata(chan, filename, tmp2, sizeof(tmp2) - 1, 0);
if (!res)
pbx_builtin_setvar_helper(chan, tmp, tmp2);
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp2);
}
LOCAL_USER_REMOVE(u);
return res;

View File

@@ -21,6 +21,7 @@
#include <asterisk/dsp.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Trivial Record Application";
@@ -29,19 +30,10 @@ static char *app = "Record";
static char *synopsis = "Record to a file";
static char *descrip =
" Record(filename:format|silence[|maxduration][|option])\n\n"
"Records from the channel into a given filename. If the file exists it will\n"
"be overwritten.\n"
"- 'format' is the format of the file type to be recorded (wav, gsm, etc).\n"
"- 'silence' is the number of seconds of silence to allow before returning.\n"
"- 'maxduration' is the maximum recording duration in seconds. If missing\n"
"or 0 there is no maximum.\n"
"- 'option' may be 'skip' to return immediately if the line is not up,\n"
"or 'noanswer' to attempt to record even if the line is not up.\n\n"
"If filename contains '%d', these characters will be replaced with a number\n"
"incremented by one each time the file is recorded. \n\n"
"Formats: g723, g729, gsm, h263, ulaw, alaw, vox, wav, WAV\n\n"
"User can press '#' to terminate the recording and continue to the next priority.\n\n"
" Record(filename:extension|silence): Records from the channel into a given\n"
"filename. If the file exists it will be overwritten. The 'extension'\n"
"is the extension of the file type to be recorded (wav, gsm, etc).\n"
"'silence' is the number of seconds of silence to allow before returning.\n"
"Returns -1 when the user hangs up.\n";
STANDARD_LOCAL_USER;
@@ -56,7 +48,7 @@ static int record_exec(struct ast_channel *chan, void *data)
char fil[256];
char tmp[256];
char ext[10];
char *vdata;
char * vdata; /* Used so I don't have to typecast every use of *data */
int i = 0;
int j = 0;
@@ -70,128 +62,64 @@ static int record_exec(struct ast_channel *chan, void *data)
int silence = 0; /* amount of silence to allow */
int gotsilence = 0; /* did we timeout for silence? */
char silencestr[5];
char durationstr[8];
int maxduration = 0; /* max duration of recording */
int gottimeout = 0; /* did we timeout for maxduration exceeded? */
time_t timeout = 0;
char option[16];
int option_skip = 0;
int option_noanswer = 0;
int k = 0;
int rfmt = 0;
int flags;
char *end=NULL;
char *p=NULL;
vdata = data; /* explained above */
/* The next few lines of code parse out the filename and header from the input string */
if (!data) { /* no data implies no filename or anything is present */
if (!vdata) { /* no data implies no filename or anything is present */
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
return -1;
}
vdata = ast_strdupa(data);
p = vdata;
while(p && (p=strchr(p,':'))) {
end=p;
if(!strcasecmp(end,":end")) {
*end='\0';
end++;
break;
}
p++;
end=NULL;
}
for (; vdata[i] && (vdata[i] != ':') && (vdata[i] != '|'); i++ ) {
if ((vdata[i] == '%') && (vdata[i+1] == 'd')) {
percentflag = 1; /* the wildcard is used */
}
if (j < sizeof(fil) - 1)
fil[j++] = vdata[i];
if (i == strlen(vdata) ) {
ast_log(LOG_WARNING, "No extension found\n");
return -1;
}
fil[i] = vdata[i];
}
fil[j] = '\0';
fil[i++] = '\0';
if (vdata[i] != ':') {
ast_log(LOG_WARNING, "No extension found\n");
return -1;
}
i++;
j = 0;
for (; vdata[i] && (vdata[i] != '|'); i++)
if (j < sizeof(ext) - 1)
ext[j++] = vdata[i];
for (; j < 10 && i < strlen(data) && (vdata[i] != '|'); i++, j++)
ext[j] = vdata[i];
ext[j] = '\0';
if (vdata[i] == '|')
i++;
if (vdata[i] && (vdata[i] == '|')) i++;
for (; vdata[i] && (vdata[i] != '|') && (k < 3) && i < strlen(data); i++, k++)
silencestr[k] = vdata[i];
silencestr[k] = '\0';
j = 0;
for (; vdata[i] && (vdata[i] != '|'); i++)
if (j < sizeof(silencestr) - 1)
silencestr[j++] = vdata[i];
silencestr[j] = '\0';
if (j > 0) {
if (silencestr) {
silence = atoi(silencestr);
if (silence > 0)
silence *= 1000;
}
if (vdata[i] == '|')
i++;
j = 0;
for (; vdata[i] && (vdata[i] != '|'); i++)
if (j < sizeof(durationstr) - 1)
durationstr[j++] = vdata[i];
durationstr[j] = '\0';
if (j > 0)
maxduration = atoi(durationstr);
if (vdata[i] == '|')
i++;
j = 0;
for (; vdata[i] && (vdata[i] != '|'); i++)
if (j < sizeof(option) - 1)
option[j++] = vdata[i];
option[j] = '\0';
if (!strcasecmp(option, "skip"))
option_skip = 1;
if (!strcasecmp(option, "noanswer"))
option_noanswer = 1;
/* done parsing */
/* these are to allow the use of the %d in the config file for a wild card of sort to
create a new file with the inputed name scheme */
if (percentflag) {
do {
snprintf(tmp, sizeof(tmp), fil, count);
snprintf(tmp, 256, fil, count);
count++;
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
} else
strncpy(tmp, fil, sizeof(tmp)-1);
strncpy(tmp, fil, 256-1);
/* end of routine mentioned */
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
LOCAL_USER_REMOVE(u);
return 0;
} else if (!option_noanswer) {
/* Otherwise answer unless we're supposed to record while on-hook */
res = ast_answer(chan);
}
res = ast_answer(chan); /* Shouldn't need this, but checking to see if channel is already answered
* Theoretically asterisk should already have answered before running the app */
}
if (!res) {
@@ -222,21 +150,10 @@ static int record_exec(struct ast_channel *chan, void *data)
ast_dsp_set_threshold(sildet, 256);
}
flags = end ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
if (s) {
if (maxduration > 0)
timeout = time(NULL) + (time_t)maxduration;
while (ast_waitfor(chan, -1) > -1) {
if (maxduration > 0 && time(NULL) > timeout) {
gottimeout = 1;
break;
}
f = ast_read(chan);
if (!f) {
res = -1;
@@ -289,7 +206,7 @@ static int record_exec(struct ast_channel *chan, void *data)
if (gotsilence) {
ast_stream_rewind(s, silence-1000);
ast_truncstream(s);
} else if (!gottimeout) {
} else {
/* Strip off the last 1/4 second of it */
ast_stream_rewind(s, 250);
ast_truncstream(s);
@@ -301,7 +218,7 @@ static int record_exec(struct ast_channel *chan, void *data)
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
LOCAL_USER_REMOVE(u);
if ((silence > 0) && rfmt) {
if (silence > 0) {
res = ast_set_read_format(chan, rfmt);
if (res)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,6 @@
static char *tdesc = "Say time";
static char *app_sayunixtime = "SayUnixTime";
static char *app_datetime = "DateTime";
static char *sayunixtime_synopsis = "Says a specified time in a custom format";
@@ -40,15 +39,6 @@ static char *sayunixtime_descrip =
" format: a format the time is to be said in. See voicemail.conf.\n"
" defaults to \"ABdY 'digits/at' IMp\"\n"
" Returns 0 or -1 on hangup.\n";
static char *datetime_descrip =
"DateTime([unixtime][|[timezone][|format]])\n"
" unixtime: time, in seconds since Jan 1, 1970. May be negative.\n"
" defaults to now.\n"
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
" defaults to machine default.\n"
" format: a format the time is to be said in. See voicemail.conf.\n"
" defaults to \"ABdY 'digits/at' IMp\"\n"
" Returns 0 or -1 on hangup.\n";
STANDARD_LOCAL_USER;
@@ -104,23 +94,13 @@ static int sayunixtime_exec(struct ast_channel *chan, void *data)
int unload_module(void)
{
int res;
STANDARD_HANGUP_LOCALUSERS;
res = ast_unregister_application(app_sayunixtime);
if (! res)
return ast_unregister_application(app_datetime);
else
return res;
return ast_unregister_application(app_sayunixtime);
}
int load_module(void)
{
int res;
res = ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
if (! res)
return ast_register_application(app_datetime, sayunixtime_exec, sayunixtime_synopsis, datetime_descrip);
else
return res;
return ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
}
char *description(void)

View File

@@ -19,10 +19,9 @@
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include <asterisk/app.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Send DTMF digits Application";
@@ -31,9 +30,8 @@ static char *app = "SendDTMF";
static char *synopsis = "Sends arbitrary DTMF digits";
static char *descrip =
" SendDTMF(digits): Sends DTMF digits on a channel. \n"
" Accepted digits: 0-9, *#abcd\n"
" Returns 0 on success or -1 on a hangup.\n";
" SendDTMF(digits): Sends DTMF digits on a channel. Returns 0 on success"
"or -1 on a hangup.\n";
STANDARD_LOCAL_USER;
@@ -44,13 +42,30 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
int res = 0;
struct localuser *u;
char *digits = data;
if (!digits || ast_strlen_zero(digits)) {
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits or *#aAbBcCdD)\n");
struct ast_frame f;
int x;
if (!digits || !strlen(digits)) {
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits)\n");
return -1;
}
LOCAL_USER_ADD(u);
res = ast_dtmf_stream(chan,NULL,digits,250);
for (x=0;x<strlen(digits);x++) {
memset(&f, 0, sizeof(f));
f.frametype = AST_FRAME_DTMF;
f.subclass = digits[x];
f.src = "app_senddtmf";
res = ast_write(chan, &f);
if (res)
break;
/* Wait 250ms */
res = ast_safe_sleep(chan, 250);
if (res)
break;
}
if (!res)
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Sent digit string '%s' on %s\n", digits, chan->name);
LOCAL_USER_REMOVE(u);
return res;
}

View File

@@ -1,94 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to transmit a text message
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <string.h>
#include <stdlib.h>
static char *tdesc = "Send Text Applications";
static char *app = "SendText";
static char *synopsis = "Send a Text Message";
static char *descrip =
" SendText(text): Sends text to client. If the client\n"
"does not support text transport, and there exists a step with\n"
"priority n + 101, then execution will continue at that step.\n"
"Otherwise, execution will continue at the next priority level.\n"
"SendText only returns 0 if the text was sent correctly or if\n"
"the channel does not support text transport, and -1 otherwise.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int sendtext_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
if (!data || !strlen((char *)data)) {
ast_log(LOG_WARNING, "SendText requires an argument (text)\n");
return -1;
}
LOCAL_USER_ADD(u);
ast_mutex_lock(&chan->lock);
if (!chan->pvt->send_text) {
ast_mutex_unlock(&chan->lock);
/* Does not support transport */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
LOCAL_USER_REMOVE(u);
return 0;
}
ast_mutex_unlock(&chan->lock);
res = ast_sendtext(chan, (char *)data);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, sendtext_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,82 +19,9 @@
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/callerid.h>
#include <string.h>
#include <stdlib.h>
static char *app2 = "SetCallerPres";
static char *synopsis2 = "Set CallerID Presentation";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static struct {
int val;
char *name;
} preses[] = {
{ AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened" },
{ AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen" },
{ AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen" },
{ AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed" },
{ AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED , "prohib_not_screened" },
{ AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen" },
{ AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen" },
{ AST_PRES_PROHIB_NETWORK_NUMBER, "prohib" },
{ AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable" },
};
static char *descrip2 =
" SetCallerPres(presentation): Set Caller*ID presentation on\n"
"a call to a new value. Sets ANI as well if a flag is used.\n"
"Always returns 0. Valid presentations are:\n"
"\n"
" allowed_not_screened : Presentation Allowed, Not Screened\n"
" allowed_passed_screen : Presentation Allowed, Passed Screen\n"
" allowed_failed_screen : Presentation Allowed, Failed Screen\n"
" allowed : Presentation Allowed, Network Number\n"
" prohib_not_screened : Presentation Prohibited, Not Screened\n"
" prohib_passed_screen : Presentation Prohibited, Passed Screen\n"
" prohib_failed_screen : Presentation Prohibited, Failed Screen\n"
" prohib : Presentation Prohibited, Network Number\n"
" unavailable : Number Unavailable\n"
"\n"
;
static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char tmp[256] = "";
struct localuser *u;
int x;
char *opts;
int pres = -1;
if (data)
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
opts = strchr(tmp, '|');
if (opts) {
*opts = '\0';
opts++;
}
for (x=0;x<sizeof(preses) / sizeof(preses[0]);x++) {
if (!strcasecmp(preses[x].name, tmp)) {
pres = preses[x].val;
break;
}
}
if (pres < 0) {
ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show application SetCallerPres')\n", tmp);
return 0;
}
LOCAL_USER_ADD(u);
chan->callingpres = pres;
LOCAL_USER_REMOVE(u);
return res;
}
#include <pthread.h>
static char *tdesc = "Set CallerID Application";
@@ -106,6 +33,10 @@ static char *descrip =
" SetCallerID(clid[|a]): Set Caller*ID on a call to a new\n"
"value. Sets ANI as well if a flag is used. Always returns 0\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int setcallerid_exec(struct ast_channel *chan, void *data)
{
int res = 0;
@@ -131,13 +62,11 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
ast_unregister_application(app2);
return ast_unregister_application(app);
}
int load_module(void)
{
ast_register_application(app2, setcallerid_pres_exec, synopsis2, descrip2);
return ast_register_application(app, setcallerid_exec, synopsis, descrip);
}

View File

@@ -17,9 +17,7 @@
#include <asterisk/module.h>
#include <asterisk/pbx.h>
#include <asterisk/logger.h>
#include <asterisk/config.h>
#include <asterisk/manager.h>
#include <asterisk/utils.h>
#include <stdlib.h>
#include <string.h>
@@ -61,41 +59,6 @@ STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int action_setcdruserfield(struct mansession *s, struct message *m)
{
struct ast_channel *c = NULL;
char *userfield = astman_get_header(m, "UserField");
char *channel = astman_get_header(m, "Channel");
char *append = astman_get_header(m, "Append");
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "No Channel specified");
return 0;
}
if (ast_strlen_zero(userfield)) {
astman_send_error(s, m, "No UserField specified");
return 0;
}
c = ast_channel_walk_locked(NULL);
while (c) {
if (!strcasecmp(c->name, channel))
break;
ast_mutex_unlock(&c->lock);
c = ast_channel_walk_locked(c);
}
if (!c) {
astman_send_error(s, m, "No such channel");
return 0;
}
if (ast_true(append))
ast_cdr_appenduserfield(c, userfield);
else
ast_cdr_setuserfield(c, userfield);
ast_mutex_unlock(&c->lock);
astman_send_ack(s, m, "CDR Userfield Set");
return 0;
}
static int setcdruserfield_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
@@ -134,7 +97,6 @@ int unload_module(void)
STANDARD_HANGUP_LOCALUSERS;
res = ast_unregister_application(setcdruserfield_app);
res |= ast_unregister_application(appendcdruserfield_app);
ast_manager_unregister("SetCDRUserField");
return res;
}
@@ -143,7 +105,7 @@ int load_module(void)
int res;
res = ast_register_application(setcdruserfield_app, setcdruserfield_exec, setcdruserfield_synopsis, setcdruserfield_descrip);
res |= ast_register_application(appendcdruserfield_app, appendcdruserfield_exec, appendcdruserfield_synopsis, appendcdruserfield_descrip);
ast_manager_register("SetCDRUserField", EVENT_FLAG_CALL, action_setcdruserfield, "Set the CDR UserField");
return res;
}

View File

@@ -20,9 +20,9 @@
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/callerid.h>
#include <asterisk/utils.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Set CallerID Name";
@@ -63,17 +63,17 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
ast_callerid_parse(oldcid, &n, &l);
n = tmp;
if (!ast_strlen_zero(n)) {
if (l && !ast_strlen_zero(l))
if (strlen(n)) {
if (l && strlen(l))
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
else
strncpy(newcid, tmp, sizeof(newcid) - 1);
} else if (l && !ast_strlen_zero(l)) {
} else if (l && strlen(l)) {
strncpy(newcid, l, sizeof(newcid) - 1);
}
} else
strncpy(newcid, tmp, sizeof(newcid) - 1);
ast_set_callerid(chan, !ast_strlen_zero(newcid) ? newcid : NULL, anitoo);
strncpy(newcid, tmp, sizeof(newcid));
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
LOCAL_USER_REMOVE(u);
return res;
}

View File

@@ -21,9 +21,9 @@
#include <asterisk/translate.h>
#include <asterisk/image.h>
#include <asterisk/callerid.h>
#include <asterisk/utils.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Set CallerID Number";
@@ -64,17 +64,17 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
ast_callerid_parse(oldcid, &n, &l);
l = tmp;
if (!ast_strlen_zero(l)) {
if (n && !ast_strlen_zero(n))
if (strlen(l)) {
if (n && strlen(n))
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
else
strncpy(newcid, tmp, sizeof(newcid) - 1);
} else if (n && !ast_strlen_zero(n)) {
} else if (n && strlen(n)) {
strncpy(newcid, n, sizeof(newcid) - 1);
}
} else
strncpy(newcid, tmp, sizeof(newcid) - 1);
ast_set_callerid(chan, !ast_strlen_zero(newcid) ? newcid : NULL, anitoo);
strncpy(newcid, tmp, sizeof(newcid));
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
LOCAL_USER_REMOVE(u);
return res;
}

View File

@@ -16,10 +16,10 @@
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
static char *tdesc = "Trivial skeleton Application";
static char *app = "skel";

File diff suppressed because it is too large Load Diff

View File

@@ -17,12 +17,14 @@
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *synopsis = "Soft Hangup Application";
static char *tdesc = "Hangs up the requested channel";
@@ -45,15 +47,13 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
return 0;
}
LOCAL_USER_ADD(u);
c = ast_channel_walk_locked(NULL);
c = ast_channel_walk(NULL);
while (c) {
if (!strcasecmp(c->name, data)) {
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
ast_mutex_unlock(&c->lock);
break;
}
ast_mutex_unlock(&c->lock);
c = ast_channel_walk_locked(c);
c = ast_channel_walk(c);
}
LOCAL_USER_REMOVE(u);

View File

@@ -5,7 +5,7 @@
*
* Copyright (C) 2002, Christos Ricudis
*
* Christos Ricudis <ricudis@itc.auth.gr>
* Christos Ricudis <ricudis@paiko.gr>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -26,9 +26,10 @@
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include "libpq-fe.h"
#define EXTRA_LOG 0
static char *tdesc = "Simple PostgreSQL Interface";
@@ -38,67 +39,57 @@ static char *app = "PGSQL";
static char *synopsis = "Do several SQLy things";
static char *descrip =
"PGSQL(): Do several SQLy things\n"
"Syntax:\n"
" PGSQL(Connect var option-string)\n"
" Connects to a database. Option string contains standard PostgreSQL\n"
" parameters like host=, dbname=, user=. Connection identifer returned\n"
" in ${var}\n"
" PGSQL(Query var ${connection_identifier} query-string)\n"
" Executes standard SQL query contained in query-string using established\n"
" connection identified by ${connection_identifier}. Reseult of query is\n"
" is stored in ${var}.\n"
" PGSQL(Fetch statusvar ${result_identifier} var1 var2 ... varn)\n"
" Fetches a single row from a result set contained in ${result_identifier}.\n"
" Assigns returned fields to ${var1} ... ${varn}. ${statusvar} is set TRUE\n"
" if additional rows exist in reseult set.\n"
" PGSQL(Clear ${result_identifier})\n"
" Frees memory and datastructures associated with result set.\n"
" PGSQL(Disconnect ${connection_identifier})\n"
" Disconnects from named connection to PostgreSQL.\n" ;
" PGSQL(): Do several SQLy things\n";
/*
Syntax of SQL commands :
Connect var option-string
Connect #var option-string
Connects to a database using the option-string and stores the
connection identifier in ${var}
connection identifier in $var
Query var ${connection_identifier} query-string
Query var connection-identifier query-string
Submits query-string to database backend and stores the result
identifier in ${var}
Fetch statusvar ${result_identifier} var1 var2 var3 ... varn
Fetch statusvar result-identifier var1 var2 var3 ... varn
Fetches a row from the query and stores end-of-table status in
${statusvar} and columns in ${var1}..${varn}
Clear ${result_identifier}
Clear result-identifier
Clears data structures associated with ${result_identifier}
Clears data structures associated with result-identifier
Disconnect ${connection_identifier}
Disconnect connection-identifier
Disconnects from named connection
EXAMPLES OF USE :
exten => s,2,PGSQL(Connect connid host=localhost user=asterisk dbname=credit)
exten => s,3,PGSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM})
exten => s,4,PGSQL(Fetch fetchid ${resultid} datavar1 datavar2)
exten => s,5,GotoIf(${fetchid}?6:8)
exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.")
exten => s,7,Goto(s,4)
exten => s,8,PGSQL(Clear ${resultid})
exten => s,9,PGSQL(Disconnect ${connid})
(
$2 = Connection Identifier
$3 = Result Identifier
$4 = Fetch Status Identifier (0 = no more rows)
$5, $6 = Data variables
)
exten => s,2,PGSQL,"Connect connid host=localhost user=asterisk dbname=credit";
exten => s,3,PGSQL,"Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${callerid}";
exten => s,4,PGSQL,"Fetch fetchid ${resultid} datavar1 datavar2";
exten => s,5,GotoIf,"${fetchid}=1?s|6:s|8";
exten => s,6,blablabla ${datavar1} ${datavar2} (does blablabla, datavar1 = username, datavar2 = credit);
exten => s,7,Goto,s|4
exten => s,8,PGSQL,"Clear ${resultid}";
exten => s,9,PGSQL,"Disconnect ${connid}";
*/
@@ -210,8 +201,8 @@ static int del_identifier(int identifier,int identifier_type) {
static int aPGSQL_connect(struct ast_channel *chan, void *data) {
char *s1;
char s[100] = "";
char *s1,*s4;
char s[100];
char *optionstring;
char *var;
int l;
@@ -224,7 +215,7 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
res=0;
l=strlen(data)+2;
s1=malloc(l);
strncpy(s1, data, l -1);
strncpy(s1,data,l);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
var=strsep(&stringp," ");
@@ -238,7 +229,8 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
} else {
ast_log(LOG_WARNING,"adding identifier\n");
id=add_identifier(AST_PGSQL_ID_CONNID,karoto);
snprintf(s, sizeof(s), "%d", id);
s4=&s[0];
sprintf(s4,"%d",id);
pbx_builtin_setvar_helper(chan,var,s);
}
@@ -248,9 +240,8 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
static int aPGSQL_query(struct ast_channel *chan, void *data) {
char *s1,*s2,*s3,*s4;
char s[100] = "";
char *s1,*s2,*s3,*s4,*s5;
char s[100];
char *querystring;
char *var;
int l;
@@ -265,7 +256,7 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
l=strlen(data)+2;
s1=malloc(l);
s2=malloc(l);
strncpy(s1, data, l - 1);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
@@ -294,21 +285,21 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
}
nres=PQnfields(PGSQLres);
id1=add_identifier(AST_PGSQL_ID_RESID,PGSQLres);
snprintf(s, sizeof(s), "%d", id1);
s5=&s[0];
sprintf(s5,"%d",id1);
pbx_builtin_setvar_helper(chan,var,s);
break;
}
free(s1);
free(s2);
return(res);
}
static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
char *s1,*s2,*fetchid_var,*s4,*s5,*s6,*s7;
char *s1,*s2,*s3,*s4,*s5,*s6,*s7;
char s[100];
char *var;
int l;
@@ -328,16 +319,16 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
s7=NULL;
s1=malloc(l);
s2=malloc(l);
strncpy(s1, data, l - 1);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
fetchid_var=strsep(&stringp," ");
s3=strsep(&stringp," ");
while (1) { // ugly trick to make branches with break;
var=fetchid_var; // fetchid
var=s3; // fetchid
fnd=0;
AST_LIST_TRAVERSE(headp,variables,entries) {
if (strncasecmp(ast_var_name(variables),fetchid_var,strlen(fetchid_var))==0) {
if (strncasecmp(ast_var_name(variables),s3,strlen(s3))==0) {
s7=ast_var_value(variables);
fnd=1;
break;
@@ -346,7 +337,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
if (fnd==0) {
s7="0";
pbx_builtin_setvar_helper(chan,fetchid_var,s7);
pbx_builtin_setvar_helper(chan,s3,s7);
}
s4=strsep(&stringp," ");
@@ -358,14 +349,12 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
}
id=atoi(s7); //fetchid
if ((lalares=find_identifier(id,AST_PGSQL_ID_FETCHID))==NULL) {
i=0; // fetching the very first row
i=0;
} else {
i=*lalares;
free(lalares);
del_identifier(id,AST_PGSQL_ID_FETCHID); // will re-add it a bit later
del_identifier(id,AST_PGSQL_ID_FETCHID);
}
if (i<PQntuples(PGSQLres)) {
nres=PQnfields(PGSQLres);
ast_log(LOG_WARNING,"ast_PGSQL_fetch : nres = %d i = %d ;\n",nres,i);
for (j=0;j<nres;j++) {
@@ -374,6 +363,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
ast_log(LOG_WARNING,"ast_PGSQL_fetch : More tuples (%d) than variables (%d)\n",nres,j);
break;
}
s6=PQgetvalue(PGSQLres,i,j);
if (s6==NULL) {
ast_log(LOG_WARNING,"PWgetvalue(res,%d,%d) returned NULL in ast_PGSQL_fetch\n",i,j);
@@ -382,16 +372,18 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
ast_log(LOG_WARNING,"===setting variable '%s' to '%s'\n",s5,s6);
pbx_builtin_setvar_helper(chan,s5,s6);
}
i++;
if (i<PQntuples(PGSQLres)) {
lalares=malloc(sizeof(int));
*lalares = ++i; // advance to the next row
id1 = add_identifier(AST_PGSQL_ID_FETCHID,lalares);
*lalares=i;
id1=add_identifier(AST_PGSQL_ID_FETCHID,lalares);
} else {
ast_log(LOG_WARNING,"ast_PGSQL_fetch : EOF\n");
id1 = 0; // no more rows
id1=0;
}
snprintf(s, sizeof(s), "%d", id1);
ast_log(LOG_WARNING,"Setting var '%s' to value '%s'\n",fetchid_var,s);
pbx_builtin_setvar_helper(chan,fetchid_var,s);
s5=&s[0];
sprintf(s5,"%d",id1);
ast_log(LOG_WARNING,"Setting var '%s' to value '%s'\n",s3,s);
pbx_builtin_setvar_helper(chan,s3,s);
break;
}
@@ -411,7 +403,7 @@ static int aPGSQL_reset(struct ast_channel *chan, void *data) {
l=strlen(data)+2;
s1=malloc(l);
strncpy(s1, data, l - 1);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
@@ -437,7 +429,7 @@ static int aPGSQL_clear(struct ast_channel *chan, void *data) {
l=strlen(data)+2;
s1=malloc(l);
strncpy(s1, data, l - 1);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
@@ -467,7 +459,7 @@ static int aPGSQL_disconnect(struct ast_channel *chan, void *data) {
l=strlen(data)+2;
s1=malloc(l);
strncpy(s1, data, l - 1);
strcpy(s1,data);
stringp=s1;
strsep(&stringp," "); // eat the first token, we already know it :P
s3=strsep(&stringp," ");
@@ -495,10 +487,6 @@ static int PGSQL_exec(struct ast_channel *chan, void *data)
struct localuser *u;
int result;
#if EXTRA_LOG
printf("PRSQL_exec: data=%s\n",(char*)data);
#endif
if (!data) {
ast_log(LOG_WARNING, "APP_PGSQL requires an argument (see manual)\n");
return -1;

View File

@@ -17,12 +17,14 @@
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Strip trailing digits";
static char *descrip =
@@ -45,27 +47,16 @@ LOCAL_USER_DECL;
static int striplsd_exec(struct ast_channel *chan, void *data)
{
char newexten[AST_MAX_EXTENSION] = "";
int maxbytes = 0;
int stripcount = 0;
int extlen = strlen(chan->exten);
maxbytes = sizeof(newexten) - 1;
if (data) {
stripcount = atoi(data);
}
if (!stripcount) {
ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
return 0;
}
if (extlen > stripcount) {
if (extlen - stripcount <= maxbytes) {
maxbytes = extlen - stripcount;
}
strncpy(newexten, chan->exten, maxbytes);
}
strncpy(chan->exten, newexten, sizeof(chan->exten)-1);
return 0;
char newexten[AST_MAX_EXTENSION] = "";
if (!data || !atoi(data)) {
ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
return 0;
}
if (strlen(chan->exten) > atoi(data)) {
strncpy(newexten, chan->exten, strlen(chan->exten)-atoi(data));
}
strncpy(chan->exten, newexten, sizeof(chan->exten)-1);
return 0;
}
int unload_module(void)

View File

@@ -18,17 +18,17 @@
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/pbx.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
static char *tdesc = "(Deprecated) Save substring digits in a given variable";
#include <pthread.h>
static char *tdesc = "Save substring digits in a given variable";
static char *descrip =
" (Deprecated, use ${variable:a:b} instead)\n"
"\n"
" SubString(variable=string_of_digits|count1|count2): Assigns the substring\n"
"of string_of_digits to a given variable. Parameter count1 may be positive\n"
"or negative. If it's positive then we skip the first count1 digits from the\n"
@@ -48,7 +48,7 @@ static char *descrip =
static char *app = "SubString";
static char *synopsis = "(Deprecated) Save substring digits in a given variable";
static char *synopsis = "Save substring digits in a given variable";
STANDARD_LOCAL_USER;
@@ -59,10 +59,9 @@ static int substring_exec(struct ast_channel *chan, void *data)
char newexten[AST_MAX_EXTENSION] = "";
char *count1, *count2;
char *first, *second, *stringp;
stringp=alloca(strlen(data)+1);
ast_log(LOG_WARNING, "The use of Substring application is deprecated. Please use ${variable:a:b} instead\n");
strncpy(stringp,data,strlen(data));
strncpy(stringp,data,strlen(data)+1);
if (strchr(stringp,'|')&&strchr(stringp,'=')) {
int icount1,icount2;
first=strsep(&stringp,"=");

View File

@@ -3,9 +3,9 @@
*
* Execute arbitrary system commands
*
* Copyright (C) 1999-2004, Digium, Inc.
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -17,23 +17,20 @@
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/app.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
static char *tdesc = "Generic System() application";
static char *app = "System";
static char *app2 = "TrySystem";
static char *synopsis = "Execute a system command";
static char *synopsis2 = "Try executing a system command";
static char *descrip =
" System(command): Executes a command by using system(). Returns -1 on\n"
"failure to execute the specified command. If the command itself executes\n"
@@ -41,37 +38,28 @@ static char *descrip =
"priority of the current instance, then the channel will be setup to\n"
"continue at that priority level. Otherwise, System returns 0.\n";
static char *descrip2 =
" TrySystem(command): Executes a command by using system(). Returns 0\n"
"on any situation. If the command itself executes but is in error, and if\n"
"there exists a priority n + 101, where 'n' is the priority of the current\n"
"instance, then the channel will be setup to continue at that\n"
"priority level. Otherwise, System returns 0.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
static int system_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
if (!data) {
ast_log(LOG_WARNING, "System requires an argument(command)\n");
return failmode;
return -1;
}
LOCAL_USER_ADD(u);
/* Do our thing here */
res = ast_safe_system((char *)data);
if ((res < 0) && (errno != ECHILD)) {
res = system((char *)data);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
res = failmode;
res = -1;
} else if (res == 127) {
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
res = failmode;
res = -1;
} else {
if (res < 0)
res = 0;
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority+=100;
res = 0;
@@ -80,26 +68,14 @@ static int system_exec_helper(struct ast_channel *chan, void *data, int failmode
return res;
}
static int system_exec(struct ast_channel *chan, void *data)
{
return system_exec_helper(chan, data, -1);
}
static int trysystem_exec(struct ast_channel *chan, void *data)
{
return system_exec_helper(chan, data, 0);
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
ast_unregister_application(app2);
return ast_unregister_application(app);
}
int load_module(void)
{
ast_register_application(app2, trysystem_exec, synopsis2, descrip2);
return ast_register_application(app, system_exec, synopsis, descrip);
}

View File

@@ -1,218 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Playback a file with audio detect
*
* Copyright (C) 2004, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/utils.h>
#include <asterisk/dsp.h>
#include <string.h>
#include <stdlib.h>
static char *tdesc = "Playback with Talk Detection";
static char *app = "BackgroundDetect";
static char *synopsis = "Background a file with talk detect";
static char *descrip =
" BackgroundDetect(filename[|sil[|min|[max]]]): Plays back a given\n"
"filename, waiting for interruption from a given digit (the digit must\n"
"start the beginning of a valid extension, or it will be ignored).\n"
"During the playback of the file, audio is monitored in the receive\n"
"direction, and if a period of non-silence which is greater than 'min' ms\n"
"yet less than 'max' ms is followed by silence for at least 'sil' ms then\n"
"the audio playback is aborted and processing jumps to the 'talk' extension\n"
"if available. If unspecified, sil, min, and max default to 1000, 100, and\n"
"infinity respectively. Returns -1 on hangup, and 0 on successful playback\n"
"completion with no exit conditions.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int background_detect_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char tmp[256];
char *options;
char *stringp;
struct ast_frame *fr;
int notsilent=0;
struct timeval start = { 0, 0}, end = {0, 0};
int sil = 1000;
int min = 100;
int max = -1;
int x;
int origrformat=0;
struct ast_dsp *dsp;
if (!data || ast_strlen_zero((char *)data)) {
ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
return -1;
}
strncpy(tmp, (char *)data, sizeof(tmp)-1);
stringp=tmp;
strsep(&stringp, "|");
options = strsep(&stringp, "|");
if (options) {
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
sil = x;
options = strsep(&stringp, "|");
if (options) {
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
min = x;
options = strsep(&stringp, "|");
if (options) {
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
max = x;
}
}
}
ast_log(LOG_DEBUG, "Preparing detect of '%s', sil=%d,min=%d,max=%d\n",
tmp, sil, min, max);
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
/* Otherwise answer unless we're supposed to send this while on-hook */
res = ast_answer(chan);
}
if (!res) {
origrformat = chan->readformat;
if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)))
ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
}
if (!(dsp = ast_dsp_new())) {
ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
res = -1;
}
if (!res) {
ast_stopstream(chan);
res = ast_streamfile(chan, tmp, chan->language);
if (!res) {
while(chan->stream) {
res = ast_sched_wait(chan->sched);
if ((res < 0) && !chan->timingfunc) {
res = 0;
break;
}
if (res < 0)
res = 1000;
res = ast_waitfor(chan, res);
if (res < 0) {
ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
break;
} else if (res > 0) {
fr = ast_read(chan);
if (!fr) {
res = -1;
break;
} else if (fr->frametype == AST_FRAME_DTMF) {
char t[2];
t[0] = fr->subclass;
t[1] = '\0';
if (ast_canmatch_extension(chan, chan->context, t, 1, chan->callerid)) {
/* They entered a valid extension, or might be anyhow */
res = fr->subclass;
ast_frfree(fr);
break;
}
} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) {
int totalsilence;
int ms;
res = ast_dsp_silence(dsp, fr, &totalsilence);
if (res && (totalsilence > sil)) {
/* We've been quiet a little while */
if (notsilent) {
/* We had heard some talking */
gettimeofday(&end, NULL);
ms = (end.tv_sec - start.tv_sec) * 1000;
ms += (end.tv_usec - start.tv_usec) / 1000;
ms -= sil;
if (ms < 0)
ms = 0;
if ((ms > min) && ((max < 0) || (ms < max))) {
ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
if (ast_exists_extension(chan, chan->context, "talk", 1, chan->callerid)) {
strncpy(chan->exten, "talk", sizeof(chan->exten) -1 );
chan->priority = 0;
}
res = 0;
ast_frfree(fr);
break;
} else
ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
notsilent = 0;
}
} else {
if (!notsilent) {
/* Heard some audio, mark the begining of the token */
gettimeofday(&start, NULL);
ast_log(LOG_DEBUG, "Start of voice token!\n");
notsilent = 1;
}
}
}
ast_frfree(fr);
}
ast_sched_runq(chan->sched);
}
ast_stopstream(chan);
} else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
res = 0;
}
}
if (res > -1) {
if (origrformat && ast_set_read_format(chan, origrformat)) {
ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
chan->name, ast_getformatname(origrformat));
}
}
if (dsp)
ast_dsp_free(dsp);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, background_detect_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,473 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Applications to test connection and produce report in text file
*
* Copyright (C) 2004, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* Russell Bryant <russelb@clemson.edu>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <sys/types.h>
#include <asterisk/channel.h>
#include <asterisk/options.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include <asterisk/lock.h>
#include <asterisk/app.h>
#include <asterisk/pbx.h>
#include <asterisk/utils.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "../astconf.h"
static char *tdesc = "Interface Test Application";
static char *tests_descrip =
"TestServer(): Perform test server function and write call report.\n"
"Results stored in /var/log/asterisk/testreports/<testid>-server.txt";
static char *tests_app = "TestServer";
static char *tests_synopsis = "Execute Interface Test Server";
static char *testc_descrip =
"TestClient(testid): Executes test client with given testid.\n"
"Results stored in /var/log/asterisk/testreports/<testid>-client.txt";
static char *testc_app = "TestClient";
static char *testc_synopsis = "Execute Interface Test Client";
static int measurenoise(struct ast_channel *chan, int ms, char *who)
{
int res=0;
int mssofar;
int noise=0;
int samples=0;
int x;
short *foo;
struct timeval start, tv;
struct ast_frame *f;
int rformat;
rformat = chan->readformat;
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
ast_log(LOG_NOTICE, "Unable to set to linear mode!\n");
return -1;
}
gettimeofday(&start, NULL);
for(;;) {
gettimeofday(&tv, NULL);
mssofar = (tv.tv_sec - start.tv_sec) * 1000;
mssofar += (tv.tv_usec - start.tv_usec) / 1000;
if (mssofar > ms)
break;
res = ast_waitfor(chan, ms - mssofar);
if (res < 1)
break;
f = ast_read(chan);
if (!f) {
res = -1;
break;
}
if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
foo = (short *)f->data;
for (x=0;x<f->samples;x++) {
noise += abs(foo[x]);
samples++;
}
}
}
if (rformat) {
if (ast_set_read_format(chan, rformat)) {
ast_log(LOG_NOTICE, "Unable to restore original format!\n");
return -1;
}
}
if (res < 0)
return res;
if (!samples) {
ast_log(LOG_NOTICE, "No samples were received from the other side!\n");
return -1;
}
ast_log(LOG_DEBUG, "%s: Noise: %d, samples: %d, avg: %d\n", who, noise, samples, noise / samples);
return (noise / samples);
}
static int sendnoise(struct ast_channel *chan, int ms)
{
int res;
res = ast_tonepair_start(chan, 1537, 2195, ms, 8192);
if (!res) {
res = ast_waitfordigit(chan, ms);
ast_tonepair_stop(chan);
}
return res;
}
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int testclient_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
int res = 0;
char *testid=data;
char fn[80];
char serverver[80];
FILE *f;
LOCAL_USER_ADD(u);
/* Check for test id */
if (!testid || ast_strlen_zero(testid)) {
ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
return -1;
}
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
/* Wait a few just to be sure things get started */
res = ast_safe_sleep(chan, 3000);
/* Transmit client version */
if (!res)
res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
ast_log(LOG_DEBUG, "Transmit client version\n");
/* Read server version */
ast_log(LOG_DEBUG, "Read server version\n");
if (!res)
res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
if (res > 0)
res = 0;
ast_log(LOG_DEBUG, "server version: %s\n", serverver);
if (res > 0)
res = 0;
if (!res)
res = ast_safe_sleep(chan, 1000);
/* Send test id */
if (!res)
res = ast_dtmf_stream(chan, NULL, testid, 0);
if (!res)
res = ast_dtmf_stream(chan, NULL, "#", 0);
ast_log(LOG_DEBUG, "send test identifier: %s\n", testid);
if ((res >=0) && (!ast_strlen_zero(testid))) {
/* Make the directory to hold the test results in case it's not there */
snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
mkdir(fn, 0777);
snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid);
if ((f = fopen(fn, "w+"))) {
setlinebuf(f);
fprintf(f, "CLIENTCHAN: %s\n", chan->name);
fprintf(f, "CLIENTTEST ID: %s\n", testid);
fprintf(f, "ANSWER: PASS\n");
res = 0;
if (!res) {
/* Step 1: Wait for "1" */
ast_log(LOG_DEBUG, "TestClient: 2. Wait DTMF 1\n");
res = ast_waitfordigit(chan, 3000);
fprintf(f, "WAIT DTMF 1: %s\n", (res != '1') ? "FAIL" : "PASS");
if (res == '1')
res = 0;
else
res = -1;
}
if (!res)
res = ast_safe_sleep(chan, 1000);
if (!res) {
/* Step 2: Send "2" */
ast_log(LOG_DEBUG, "TestClient: 2. Send DTMF 2\n");
res = ast_dtmf_stream(chan, NULL, "2", 0);
fprintf(f, "SEND DTMF 2: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 3: Wait one second */
ast_log(LOG_DEBUG, "TestClient: 3. Wait one second\n");
res = ast_safe_sleep(chan, 1000);
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 4: Measure noise */
ast_log(LOG_DEBUG, "TestClient: 4. Measure noise\n");
res = measurenoise(chan, 5000, "TestClient");
fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
if (res > 0)
res = 0;
}
if (!res) {
/* Step 5: Wait for "4" */
ast_log(LOG_DEBUG, "TestClient: 5. Wait DTMF 4\n");
res = ast_waitfordigit(chan, 3000);
fprintf(f, "WAIT DTMF 4: %s\n", (res != '4') ? "FAIL" : "PASS");
if (res == '4')
res = 0;
else
res = -1;
}
if (!res) {
/* Step 6: Transmit tone noise */
ast_log(LOG_DEBUG, "TestClient: 6. Transmit tone\n");
res = sendnoise(chan, 6000);
fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
}
if (!res || (res == '5')) {
/* Step 7: Wait for "5" */
ast_log(LOG_DEBUG, "TestClient: 7. Wait DTMF 5\n");
if (!res)
res = ast_waitfordigit(chan, 3000);
fprintf(f, "WAIT DTMF 5: %s\n", (res != '5') ? "FAIL" : "PASS");
if (res == '5')
res = 0;
else
res = -1;
}
if (!res) {
/* Step 8: Wait one second */
ast_log(LOG_DEBUG, "TestClient: 8. Wait one second\n");
res = ast_safe_sleep(chan, 1000);
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 9: Measure noise */
ast_log(LOG_DEBUG, "TestClient: 6. Measure tone\n");
res = measurenoise(chan, 4000, "TestClient");
fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
if (res > 0)
res = 0;
}
if (!res) {
/* Step 10: Send "7" */
ast_log(LOG_DEBUG, "TestClient: 7. Send DTMF 7\n");
res = ast_dtmf_stream(chan, NULL, "7", 0);
fprintf(f, "SEND DTMF 7: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res =0;
}
if (!res) {
/* Step 11: Wait for "8" */
ast_log(LOG_DEBUG, "TestClient: 11. Wait DTMF 8\n");
res = ast_waitfordigit(chan, 3000);
fprintf(f, "WAIT DTMF 8: %s\n", (res != '8') ? "FAIL" : "PASS");
if (res == '8')
res = 0;
else
res = -1;
}
if (!res) {
/* Step 12: Hangup! */
ast_log(LOG_DEBUG, "TestClient: 12. Hangup\n");
}
ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
fprintf(f, "-- END TEST--\n");
fclose(f);
res = -1;
} else
res = -1;
} else {
ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static int testserver_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
int res = 0;
char testid[80]="";
char fn[80];
FILE *f;
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
/* Read version */
ast_log(LOG_DEBUG, "Read client version\n");
if (!res)
res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
if (res > 0)
res = 0;
ast_log(LOG_DEBUG, "client version: %s\n", testid);
ast_log(LOG_DEBUG, "Transmit server version\n");
res = ast_safe_sleep(chan, 1000);
if (!res)
res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
if (res > 0)
res = 0;
if (!res)
res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
ast_log(LOG_DEBUG, "read test identifier: %s\n", testid);
/* Check for sneakyness */
if (strchr(testid, '/'))
res = -1;
if ((res >=0) && (!ast_strlen_zero(testid))) {
/* Got a Test ID! Whoo hoo! */
/* Make the directory to hold the test results in case it's not there */
snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
mkdir(fn, 0777);
snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid);
if ((f = fopen(fn, "w+"))) {
setlinebuf(f);
fprintf(f, "SERVERCHAN: %s\n", chan->name);
fprintf(f, "SERVERTEST ID: %s\n", testid);
fprintf(f, "ANSWER: PASS\n");
ast_log(LOG_DEBUG, "Processing Test ID '%s'\n", testid);
res = ast_safe_sleep(chan, 1000);
if (!res) {
/* Step 1: Send "1" */
ast_log(LOG_DEBUG, "TestServer: 1. Send DTMF 1\n");
res = ast_dtmf_stream(chan, NULL, "1", 0);
fprintf(f, "SEND DTMF 1: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 2: Wait for "2" */
ast_log(LOG_DEBUG, "TestServer: 2. Wait DTMF 2\n");
res = ast_waitfordigit(chan, 3000);
fprintf(f, "WAIT DTMF 2: %s\n", (res != '2') ? "FAIL" : "PASS");
if (res == '2')
res = 0;
else
res = -1;
}
if (!res) {
/* Step 3: Measure noise */
ast_log(LOG_DEBUG, "TestServer: 3. Measure noise\n");
res = measurenoise(chan, 6000, "TestServer");
fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
if (res > 0)
res = 0;
}
if (!res) {
/* Step 4: Send "4" */
ast_log(LOG_DEBUG, "TestServer: 4. Send DTMF 4\n");
res = ast_dtmf_stream(chan, NULL, "4", 0);
fprintf(f, "SEND DTMF 4: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 5: Wait one second */
ast_log(LOG_DEBUG, "TestServer: 5. Wait one second\n");
res = ast_safe_sleep(chan, 1000);
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 6: Measure noise */
ast_log(LOG_DEBUG, "TestServer: 6. Measure tone\n");
res = measurenoise(chan, 4000, "TestServer");
fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
if (res > 0)
res = 0;
}
if (!res) {
/* Step 7: Send "5" */
ast_log(LOG_DEBUG, "TestServer: 7. Send DTMF 5\n");
res = ast_dtmf_stream(chan, NULL, "5", 0);
fprintf(f, "SEND DTMF 5: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 8: Transmit tone noise */
ast_log(LOG_DEBUG, "TestServer: 8. Transmit tone\n");
res = sendnoise(chan, 6000);
fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
}
if (!res || (res == '7')) {
/* Step 9: Wait for "7" */
ast_log(LOG_DEBUG, "TestServer: 9. Wait DTMF 7\n");
if (!res)
res = ast_waitfordigit(chan, 3000);
fprintf(f, "WAIT DTMF 7: %s\n", (res != '7') ? "FAIL" : "PASS");
if (res == '7')
res = 0;
else
res = -1;
}
if (!res)
res = ast_safe_sleep(chan, 1000);
if (!res) {
/* Step 10: Send "8" */
ast_log(LOG_DEBUG, "TestServer: 10. Send DTMF 8\n");
res = ast_dtmf_stream(chan, NULL, "8", 0);
fprintf(f, "SEND DTMF 8: %s\n", (res < 0) ? "FAIL" : "PASS");
if (res > 0)
res = 0;
}
if (!res) {
/* Step 11: Wait for hangup to arrive! */
ast_log(LOG_DEBUG, "TestServer: 11. Waiting for hangup\n");
res = ast_safe_sleep(chan, 10000);
fprintf(f, "WAIT HANGUP: %s\n", (res < 0) ? "PASS" : "FAIL");
}
ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
fprintf(f, "-- END TEST--\n");
fclose(f);
res = -1;
} else
res = -1;
} else {
ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
ast_unregister_application(testc_app);
return ast_unregister_application(tests_app);
}
int load_module(void)
{
ast_register_application(testc_app, testclient_exec, testc_synopsis, testc_descrip);
return ast_register_application(tests_app, testserver_exec, tests_synopsis, tests_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key(void)
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,7 +1,7 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Transfer a caller
* Time of day - Report the time of day
*
* Copyright (C) 1999, Mark Spencer
*
@@ -22,6 +22,9 @@
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Transfer";
static char *app = "Transfer";

View File

@@ -1,145 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Caller*id name lookup - Look up the caller's name via DNS
*
* Copyright (C) 1999-2004, Digium
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/options.h>
#include <asterisk/config.h>
#include <asterisk/module.h>
#include <asterisk/enum.h>
#include <asterisk/utils.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
static char *tdesc = "TXTCIDName";
static char *app = "TXTCIDName";
static char *synopsis = "Lookup caller name from TXT record";
static char *descrip =
" TXTLookup(CallerID): Looks up a Caller Name via DNS and sets\n"
"the variable 'TXTCIDNAME'. TXTCIDName will either be blank\n"
"or return the value found in the TXT record in DNS.\n" ;
#define ENUM_CONFIG "enum.conf"
static char h323driver[80] = "";
#define H323DRIVERDEFAULT "H323"
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int txtcidname_exec(struct ast_channel *chan, void *data)
{
int res=0;
char tech[80];
char txt[256] = "";
char dest[80];
struct localuser *u;
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "TXTCIDName requires an argument (extension)\n");
res = 1;
}
LOCAL_USER_ADD(u);
if (!res) {
res = ast_get_txt(chan, data, dest, sizeof(dest), tech, sizeof(tech), txt, sizeof(txt));
}
LOCAL_USER_REMOVE(u);
/* Parse it out */
if (res > 0) {
if (!ast_strlen_zero(txt)) {
pbx_builtin_setvar_helper(chan, "TXTCIDNAME", txt);
#if 0
ast_log(LOG_DEBUG, "TXTCIDNAME got '%s'\n", txt);
#endif
}
}
if (!res) {
/* Look for a "busy" place */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
} else if (res > 0)
res = 0;
return res;
}
static int load_config(void)
{
struct ast_config *cfg;
char *s;
cfg = ast_load(ENUM_CONFIG);
if (cfg) {
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
} else {
strncpy(h323driver, s, sizeof(h323driver) - 1);
}
ast_destroy(cfg);
return 0;
}
ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
return 0;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
int res;
res = ast_register_application(app, txtcidname_exec, synopsis, descrip);
if (res)
return(res);
if ((res=load_config())) {
return(res);
}
return(0);
}
int reload(void)
{
return(load_config());
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -21,6 +21,7 @@
#include <asterisk/image.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Send URL Applications";

View File

@@ -1,106 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* UserEvent application -- send manager event
*
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/manager.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
static char *tdesc = "Custom User Event Application";
static char *app = "UserEvent";
static char *synopsis = "Send an arbitrary event to the manager interface";
static char *descrip =
" UserEvent(eventname[|body]): Sends an arbitrary event to the\n"
"manager interface, with an optional body representing additional\n"
"arguments. The format of the event will be:\n"
" Event: UserEvent<specified event name>\n"
" Channel: <channel name>\n"
" Uniqueid: <call uniqueid>\n"
" [body]\n"
"If the body is not specified, only Event, Channel, and Uniqueid fields\n"
"will be present. Returns 0.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int userevent_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
char info[512];
char eventname[512];
char *eventbody;
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "UserEvent requires an argument (eventname|optional event body)\n");
return -1;
}
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
snprintf(eventname, sizeof(eventname), "UserEvent%s", info);
eventbody = strchr(eventname, '|');
if (eventbody) {
*eventbody = '\0';
eventbody++;
}
LOCAL_USER_ADD(u);
if(eventbody) {
ast_log(LOG_DEBUG, "Sending user event: %s, %s\n", eventname, eventbody);
manager_event(EVENT_FLAG_CALL, eventname,
"Channel: %s\r\nUniqueid: %s\r\n%s\r\n",
chan->name, chan->uniqueid, eventbody);
} else {
ast_log(LOG_DEBUG, "Sending user event: %s\n", eventname);
manager_event(EVENT_FLAG_CALL, eventname,
"Channel: %s\r\nUniqueid: %s\r\n", chan->name, chan->uniqueid);
}
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, userevent_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,110 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Verbose application
*
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_verbose_v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <asterisk/options.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
static char *tdesc = "Send verbose output";
static char *app_verbose = "Verbose";
static char *verbose_synopsis = "Send arbitrary text to verbose output";
static char *verbose_descrip =
"Verbose([<level>|]<message>)\n"
" level must be an integer value. If not specified, defaults to 0."
" Always returns 0.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int verbose_exec(struct ast_channel *chan, void *data)
{
char *vtext;
int vsize;
if (data) {
vtext = ast_strdupa((char *)data);
if (vtext) {
char *tmp = strsep(&vtext, "|,");
if (vtext) {
if (sscanf(tmp, "%d", &vsize) != 1) {
vsize = 0;
ast_log(LOG_WARNING, "'%s' is not a verboser number\n", vtext);
}
} else {
vtext = tmp;
vsize = 0;
}
if (option_verbose >= vsize) {
switch (vsize) {
case 0:
ast_verbose("%s\n", vtext);
break;
case 1:
ast_verbose(VERBOSE_PREFIX_1 "%s\n", vtext);
break;
case 2:
ast_verbose(VERBOSE_PREFIX_2 "%s\n", vtext);
break;
case 3:
ast_verbose(VERBOSE_PREFIX_3 "%s\n", vtext);
break;
default:
ast_verbose(VERBOSE_PREFIX_4 "%s\n", vtext);
}
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
}
}
return 0;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app_verbose);
}
int load_module(void)
{
return ast_register_application(app_verbose, verbose_exec, verbose_synopsis, verbose_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,12 +18,14 @@
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/options.h>
#include <asterisk/lock.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *synopsis = "Wait for Ring Application";
static char *tdesc = "Waits until first ring after time";
@@ -46,7 +48,7 @@ static int waitforring_exec(struct ast_channel *chan, void *data)
int res = 0;
int ms;
if (!data || (sscanf(data, "%d", &ms) != 1)) {
ast_log(LOG_WARNING, "WaitForRing requires an argument (minimum seconds)\n");
ast_log(LOG_WARNING, "SoftHangup requires an argument (minimum seconds)\n");
return 0;
}
ms *= 1000;

View File

@@ -20,6 +20,7 @@
#include <asterisk/translate.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Block Telemarketers with Special Information Tone";

View File

@@ -25,7 +25,6 @@
#include <asterisk/options.h>
#include <asterisk/cli.h>
#include <asterisk/say.h>
#include <asterisk/utils.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
@@ -33,12 +32,8 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <pthread.h>
#include <linux/zaptel.h>
#else
#include <zaptel.h>
#endif /* __linux__ */
static char *tdesc = "Barge in on Zap channel application";
static char *app = "ZapBarge";
@@ -249,9 +244,9 @@ static int conf_exec(struct ast_channel *chan, void *data)
int retrycnt = 0;
int confflags = 0;
int confno = 0;
char confstr[80] = "";
char confstr[80];
if (data && !ast_strlen_zero(data)) {
if (data && strlen(data)) {
if ((sscanf(data, "Zap/%d", &confno) != 1) &&
(sscanf(data, "%d", &confno) != 1)) {
ast_log(LOG_WARNING, "ZapBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
@@ -264,7 +259,7 @@ static int conf_exec(struct ast_channel *chan, void *data)
while(!confno && (++retrycnt < 4)) {
/* Prompt user for conference number */
confstr[0] = '\0';
strcpy(confstr, "");
res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0);
if (res <0) goto out;
if (sscanf(confstr, "%d", &confno) != 1)

View File

@@ -20,11 +20,7 @@
#include <asterisk/options.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#ifdef __linux__
#include <sys/signal.h>
#else
#include <signal.h>
#endif /* __linux__ */
#include <stdlib.h>
#include <unistd.h>
@@ -34,12 +30,10 @@
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
/* Need some zaptel help here */
#ifdef __linux__
#include <linux/zaptel.h>
#else
#include <zaptel.h>
#endif /* __linux__ */
static char *tdesc = "Zap RAS Application";
@@ -50,7 +44,7 @@ static char *synopsis = "Executes Zaptel ISDN RAS application";
static char *descrip =
" ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
"The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
"channel to be able to use this function (No modem emulation is included).\n"
"channel to be able to use this function (No modem emulcation is included).\n"
"Your pppd must be patched to be zaptel aware. Arguments should be\n"
"separated by | characters. Always returns -1.\n";

View File

@@ -34,12 +34,8 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <pthread.h>
#include <linux/zaptel.h>
#else
#include <zaptel.h>
#endif /* __linux__ */
static char *tdesc = "Scan Zap channels application";
static char *app = "ZapScan";
@@ -47,8 +43,8 @@ static char *app = "ZapScan";
static char *synopsis = "Scan Zap channels to monitor calls";
static char *descrip =
" ZapScan allows a call center manager to monitor Zap channels in\n"
"a convenient way. Use '#' to select the next channel and use '*' to exit\n";
" ZapScan allows a call center manager to monitor\n"
"phone conversations in a convenient way.";
STANDARD_LOCAL_USER;
@@ -58,22 +54,6 @@ LOCAL_USER_DECL;
#define CONF_SIZE 160
static struct ast_channel *get_zap_channel_locked(int num) {
struct ast_channel *c=NULL;
char name[80];
snprintf(name,sizeof(name),"Zap/%d-1",num);
c = ast_channel_walk_locked(NULL);
while(c) {
if (!strcasecmp(c->name, name)) {
break;
}
ast_mutex_unlock(&c->lock);
c = ast_channel_walk_locked(c);
}
return c;
}
static int careful_write(int fd, unsigned char *data, int len)
{
int res;
@@ -107,8 +87,6 @@ static int conf_run(struct ast_channel *chan, int confno, int confflags)
int retryzap;
int origfd;
int ret = -1;
char input[4];
int ic=0;
ZT_BUFFERINFO bi;
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
@@ -210,30 +188,11 @@ zapretry:
f = ast_read(c);
if (!f)
break;
if(f->frametype == AST_FRAME_DTMF) {
if(f->subclass == '#') {
ret = 0;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
ret = 0;
break;
}
else if (f->subclass == '*') {
ret = -1;
break;
}
else {
input[ic++] = f->subclass;
}
if(ic == 3) {
input[ic++] = '\0';
ic=0;
ret = atoi(input);
ast_verbose(VERBOSE_PREFIX_3 "Zapscan: change channel to %d\n",ret);
break;
}
}
if (fd != chan->fds[0]) {
if (f->frametype == AST_FRAME_VOICE) {
} else if (fd != chan->fds[0]) {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_ULAW) {
/* Carefully write */
careful_write(fd, f->data, f->datalen);
@@ -284,56 +243,33 @@ static int conf_exec(struct ast_channel *chan, void *data)
struct localuser *u;
int confflags = 0;
int confno = 0;
char confstr[80] = "", *tmp;
struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL;
struct ast_frame *f;
int input=0;
char confstr[80], *tmp;
struct ast_channel *tempchan = NULL, *lastchan = NULL;
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
for (;;) {
if (ast_waitfor(chan, 100) < 0)
break;
f = ast_read(chan);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
ast_frfree(f);
break;
tempchan = ast_channel_walk(tempchan);
if ( !tempchan && !lastchan )
break;
if ( tempchan && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) {
ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name);
strcpy(confstr, tempchan->name);
if ((tmp = strchr(confstr,'-'))) {
*tmp = '\0';
}
ast_frfree(f);
ichan = NULL;
if(input) {
ichan = get_zap_channel_locked(input);
input = 0;
}
tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);
if ( !tempchan && !lastchan )
break;
if ( tempchan && tempchan->type && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) {
ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name);
strncpy(confstr, tempchan->name, sizeof(confstr) - 1);
ast_mutex_unlock(&tempchan->lock);
if ((tmp = strchr(confstr,'-'))) {
*tmp = '\0';
}
confno = atoi(strchr(confstr,'/') + 1);
ast_stopstream(chan);
ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
res = conf_run(chan, confno, confflags);
if (res<0) break;
input = res;
} else if (tempchan)
ast_mutex_unlock(&tempchan->lock);
lastchan = tempchan;
confno = atoi(strchr(confstr,'/') + 1);
ast_stopstream(chan);
ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language);
res = conf_run(chan, confno, confflags);
if (res<0) break;
}
lastchan = tempchan;
}
LOCAL_USER_REMOVE(u);
return res;
}

Binary file not shown.

View File

@@ -20,13 +20,6 @@
#include <asterisk/ast_expr.h>
#include <asterisk/logger.h>
#ifdef LONG_LONG_MIN
#define QUAD_MIN LONG_LONG_MIN
#endif
#ifdef LONG_LONG_MAX
#define QUAD_MAX LONG_LONG_MAX
#endif
# if ! defined(QUAD_MIN)
# define QUAD_MIN (-0x7fffffffffffffffL-1)
# endif
@@ -55,7 +48,6 @@ struct val {
struct parser_control {
struct val *result;
int pipa;
char *arg_orig;
char *argv;
char *ptrptr;
int firsttoken;
@@ -86,30 +78,10 @@ static struct val *op_rem __P((struct val *, struct val *));
static struct val *op_times __P((struct val *, struct val *));
static quad_t to_integer __P((struct val *));
static void to_string __P((struct val *));
/* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
typedef struct yyltype
{
int first_line;
int first_column;
int last_line;
int last_column;
} yyltype;
# define YYLTYPE yyltype
# define YYLTYPE_IS_TRIVIAL 1
static int ast_yyerror __P((const char *,YYLTYPE *, struct parser_control *));
#define ast_yyerror(x) ast_yyerror(x,&yyloc,kota)
static int ast_yyerror __P((const char *));
%}
%pure-parser
%locations
/* %debug for when you are having big problems */
/* %name-prefix="ast_yy" */
%union
@@ -118,7 +90,7 @@ static int ast_yyerror __P((const char *,YYLTYPE *, struct parser_control *));
}
%{
static int ast_yylex __P((YYSTYPE *, YYLTYPE *, struct parser_control *));
static int ast_yylex __P((YYSTYPE *, struct parser_control *));
%}
@@ -138,21 +110,21 @@ start: expr { ((struct parser_control *)kota)->result = $$; }
;
expr: TOKEN
| '(' expr ')' { $$ = $2; @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '|' expr { $$ = op_or ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '&' expr { $$ = op_and ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '=' expr { $$ = op_eq ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '>' expr { $$ = op_gt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '<' expr { $$ = op_lt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr GE expr { $$ = op_ge ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr LE expr { $$ = op_le ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr NE expr { $$ = op_ne ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '+' expr { $$ = op_plus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '-' expr { $$ = op_minus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '*' expr { $$ = op_times ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '/' expr { $$ = op_div ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr '%' expr { $$ = op_rem ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| expr ':' expr { $$ = op_colon ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
| '(' expr ')' { $$ = $2; }
| expr '|' expr { $$ = op_or ($1, $3); }
| expr '&' expr { $$ = op_and ($1, $3); }
| expr '=' expr { $$ = op_eq ($1, $3); }
| expr '>' expr { $$ = op_gt ($1, $3); }
| expr '<' expr { $$ = op_lt ($1, $3); }
| expr GE expr { $$ = op_ge ($1, $3); }
| expr LE expr { $$ = op_le ($1, $3); }
| expr NE expr { $$ = op_ne ($1, $3); }
| expr '+' expr { $$ = op_plus ($1, $3); }
| expr '-' expr { $$ = op_minus ($1, $3); }
| expr '*' expr { $$ = op_times ($1, $3); }
| expr '/' expr { $$ = op_div ($1, $3); }
| expr '%' expr { $$ = op_rem ($1, $3); }
| expr ':' expr { $$ = op_colon ($1, $3); }
;
@@ -215,7 +187,6 @@ struct val *vp;
}
if (vp->type == string || vp->type == numeric_string)
free (vp->u.s);
free (vp);
}
@@ -279,92 +250,19 @@ struct val *vp;
return (vp->type == string);
}
static int
ast_yylex (YYSTYPE *lvalp, YYLTYPE *yylloc, struct parser_control *karoto)
ast_yylex (YYSTYPE *lvalp, struct parser_control *karoto)
{
char *p=0;
char *t1=0;
char savep = 0;
char *savepp = 0;
char *p;
if (karoto->firsttoken==1) {
t1 = karoto->argv;
karoto->firsttoken = 0;
p=strtok_r(karoto->argv," ",&(karoto->ptrptr));
karoto->firsttoken=0;
} else {
t1 = karoto->ptrptr;
p=strtok_r(NULL," ",&(karoto->ptrptr));
}
while(*t1 && *t1 == ' ' ) /* we can remove worries about leading/multiple spaces being present */
t1++;
karoto->ptrptr = t1;
yylloc->first_column = t1 - karoto->argv;
while( *t1 && *t1 != ' ' && *t1 != '"') /* find the next space or quote */
t1++;
if( *t1 == ' ' )
{
*t1 = 0;
p = karoto->ptrptr;
karoto->ptrptr = t1+1;
yylloc->last_column = t1 - karoto->argv;
}
else if (*t1 == '"' )
{
/* opening quote. find the closing quote */
char *t2=t1+1;
while( *t2 && *t2 != '"')
t2++;
if( *t2 == '"' )
{
if( *(t2+1) == ' ' || *(t2+1) == 0 )
{
if( *(t2+1) )
{
*(t2+1) = 0;
karoto->ptrptr = t2+2;
}
else
{
karoto->ptrptr = t2+1;
}
}
else
{
/* hmmm. what if another token is here? */
/* maybe we can insert a space? */
savep = *(t2+1);
savepp = t2+1;
*(t2+1) = 0;
karoto->ptrptr = t2+1;
}
p = t1;
}
else
{
/* NOT GOOD -- no closing quote! */
p = t1;
karoto->ptrptr = t2;
}
yylloc->last_column = t2 - karoto->argv;
}
else if( *t1 == 0 )
{
if( t1 != karoto->ptrptr )
{
/* this is the last token */
p = karoto->ptrptr;
karoto->ptrptr = t1;
}
else
{
/* we are done. That was quick */
p = karoto->ptrptr;
yylloc->last_column = t1 - karoto->argv;
}
}
if( *p == 0 )
p = 0;
if (p==NULL) {
return (0);
}
@@ -382,12 +280,6 @@ ast_yylex (YYSTYPE *lvalp, YYLTYPE *yylloc, struct parser_control *karoto)
}
lvalp->val = make_str (p);
if( savep )
{
*savepp = savep; /* restore the null terminated string */
savepp = 0;
savep = 0;
}
return (TOKEN);
}
@@ -414,9 +306,7 @@ char *ast_expr (char *arg)
karoto.result = NULL;
karoto.firsttoken=1;
karoto.argv=kota;
karoto.arg_orig = arg;
/* ast_yydebug = 1; */
ast_yyparse ((void *)&karoto);
free(kota);
@@ -449,31 +339,11 @@ int main(int argc,char **argv) {
#endif
#undef ast_yyerror
#define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parser_control *karoto)
static int
ast_yyerror (const char *s)
ast_yyerror (s)
const char *s;
{
char spacebuf[8000]; /* best safe than sorry */
char spacebuf2[8000]; /* best safe than sorry */
int i=0;
spacebuf[0] = 0;
if( yylloc->first_column > 7990 ) /* if things get out of whack, why crash? */
yylloc->first_column = 7990;
if( yylloc->last_column > 7990 )
yylloc->last_column = 7990;
for(i=0;i<yylloc->first_column;i++) spacebuf[i] = ' ';
for( ;i<yylloc->last_column;i++) spacebuf[i] = '^';
spacebuf[i] = 0;
for(i=0;i<karoto->ptrptr-karoto->argv;i++) spacebuf2[i] = ' ';
spacebuf2[i++]='^';
spacebuf2[i]= 0;
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n%s\n",s,
karoto->arg_orig,spacebuf,spacebuf2);
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s\n",s);
return(0);
}
@@ -651,24 +521,19 @@ struct val *a, *b;
{
struct val *r;
if (!to_integer (a)) {
if (!to_integer (a) || !to_integer (b)) {
ast_log(LOG_WARNING,"non-numeric argument\n");
if (!to_integer (b)) {
free_value(a);
free_value(b);
return make_integer(0);
} else {
free_value(a);
return (b);
}
} else if (!to_integer(b)) {
free_value(a);
free_value(b);
return (a);
return(NULL);
}
r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
if (chk_plus (a->u.i, b->u.i, r->u.i)) {
ast_log(LOG_WARNING,"overflow\n");
free_value(a);
free_value(b);
return(NULL);
}
free_value (a);
free_value (b);
@@ -696,27 +561,19 @@ struct val *a, *b;
{
struct val *r;
if (!to_integer (a)) {
ast_log(LOG_WARNING, "non-numeric argument\n");
if (!to_integer (b)) {
free_value(a);
free_value(b);
return make_integer(0);
} else {
r = make_integer(0 - b->u.i);
free_value(a);
free_value(b);
return (r);
}
} else if (!to_integer(b)) {
ast_log(LOG_WARNING, "non-numeric argument\n");
if (!to_integer (a) || !to_integer (b)) {
free_value(a);
free_value(b);
return (a);
ast_log(LOG_WARNING, "non-numeric argument\n");
return(NULL);
}
r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
if (chk_minus (a->u.i, b->u.i, r->u.i)) {
ast_log(LOG_WARNING, "overflow\n");
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "overload\n");
return(NULL);
}
free_value (a);
free_value (b);
@@ -746,12 +603,15 @@ struct val *a, *b;
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
return(make_integer(0));
return(NULL);
}
r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
if (chk_times (a->u.i, b->u.i, r->u.i)) {
ast_log(LOG_WARNING, "overflow\n");
free_value(a);
free_value(b);
return(NULL);
}
free_value (a);
free_value (b);
@@ -776,28 +636,26 @@ struct val *a, *b;
{
struct val *r;
if (!to_integer (a)) {
if (!to_integer (a) || !to_integer (b)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
return make_integer(0);
} else if (!to_integer (b)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
return make_integer(INT_MAX);
return(NULL);
}
if (b->u.i == 0) {
ast_log(LOG_WARNING, "division by zero\n");
free_value(a);
free_value(b);
return make_integer(INT_MAX);
return(NULL);
}
r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
if (chk_div (a->u.i, b->u.i)) {
ast_log(LOG_WARNING, "overflow\n");
free_value(a);
free_value(b);
return(NULL);
}
free_value (a);
free_value (b);
@@ -814,13 +672,14 @@ struct val *a, *b;
ast_log(LOG_WARNING, "non-numeric argument\n");
free_value(a);
free_value(b);
return make_integer(0);
return(NULL);
}
if (b->u.i == 0) {
ast_log(LOG_WARNING, "div by zero\n");
free_value(a);
return (b);
free_value(b);
return(NULL);
}
r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
@@ -845,12 +704,12 @@ struct val *a, *b;
to_string(b);
/* compile regular expression */
if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
regerror (eval, &rp, errbuf, sizeof(errbuf));
ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
free_value(a);
free_value(b);
return make_str("");
return(NULL);
}
/* compare string against pattern */

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,6 @@
#define AST_AGI_DIR ASTAGIDIR
#define AST_KEY_DIR ASTVARLIBDIR "/keys"
#define AST_DB ASTVARLIBDIR "/astdb"
#define AST_TMP_DIR ASTSPOOLDIR "/tmp"
#define AST_CONFIG_FILE ASTCONFPATH
@@ -41,7 +40,6 @@ extern int load_modules(void);
extern int load_pbx(void);
/* Provided by logger.c */
extern int init_logger(void);
extern void close_logger(void);
/* Provided by frame.c */
extern int init_framer(void);
/* Provided by logger.c */

View File

@@ -1,295 +0,0 @@
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>2004-07-18</date>
</refentryinfo>
<refmeta>
<refentrytitle>
<application>asterisk</application>
</refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo>asterisk 1.0</refmiscinfo>
</refmeta>
<refnamediv>
<refname>
<application>asterisk</application>
</refname>
<refpurpose>
All-purpose telephony server.
</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>asterisk</command>
<arg><option>-hfdvVqpRgcin</option></arg>
<arg><option>-C </option><replaceable class="parameter">file</replaceable></arg>
<arg><option>-U </option><replaceable class="parameter">user</replaceable></arg>
<arg><option>-G </option><replaceable class="parameter">group</replaceable></arg>
<arg><option>-x </option><replaceable class="parameter">command</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>asterisk -r</command>
<arg><option>-v</option></arg>
<arg><option>-x </option><replaceable class="parameter">command</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<refsect1info>
<date>2004-07-01</date>
</refsect1info>
<title>DESCRIPTION</title>
<para>
<command>asterisk</command> is a full-featured telephony server which
provides Private Branch eXchange (PBX), Interactive Voice Response (IVR),
Automated Call Distribution (ACD), Voice over IP (VoIP) gatewaying,
Conferencing, and a plethora of other telephony applications to a broad
range of telephony devices including packet voice (SIP, IAX, MGCP, Skinny,
H.323) devices (both endpoints and proxies), as well as traditional TDM
hardware including T1, E1, ISDN PRI, GR-303, RBS, Loopstart, Groundstart,
ISDN BRI, and many more.
</para>
<para>
Asterisk reads most of its configuration files from configuration files
located in /etc/asterisk. Virtually all aspects of the operation of
asterisk's configuration files can be found in the sample configuration
files. The format for those files is generally beyond the scope of this
man page.
</para>
<para>
When running with <command>-c</command>, <command>-r</command> or <command>-R</command>
options, Asterisk supplies a powerful command line, including command
completion, which may be used to monitors its status, perform a variety
of administrative actions and even explore the applications that are
currently loaded into the system.
</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>-C <replaceable class="parameter">file</replaceable></term>
<listitem>
<para>
Use <filename>file</filename> as master configuration file
instead of the default, /etc/asterisk/asterisk.conf
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-c</term>
<listitem>
<para>
Provide a control console on the calling terminal.
Specifying this option implies <command>-f</command> and will cause
asterisk to no longer fork or detach from the controlling terminal.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d</term>
<listitem>
<para>
Enable extra debugging statements.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-f</term>
<listitem>
<para>
Do not fork or detach from controlling terminal.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-g</term>
<listitem>
<para>
Remove resource limit on core size, thus forcing Asterisk to dump
core in the unlikely event of a segmentation fault or abort signal.
<command>NOTE:</command> in some cases this may be incompatible
with the <command>-U</command> or <command>-G</command> flags.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-G <replaceable class="parameter">group</replaceable></term>
<listitem>
<para>
Run as group <replaceable>group</replaceable> instead of the
calling group. <command>NOTE:</command> this requires substantial work
to be sure that Asterisk's environment has permission to write
the files required for its operation, including logs, its comm
socket, the asterisk database, etc.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-h</term>
<listitem>
<para>
Provide brief summary of command line arguments and terminate.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-i</term>
<listitem>
<para>
Prompt user to intialize any encrypted private keys during startup.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-n</term>
<listitem>
<para>
Disable ANSI colors even on terminals capable of displaying them.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-p</term>
<listitem>
<para>
If supported by the operating system (and executing as root),
attempt to run with realtime priority for increased performance and
responsiveness within the Asterisk process, at the expense of other
programs running on the same machine.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-q</term>
<listitem>
<para>
Reduce default console output when running in conjunction with
console mode (<command>-c</command>).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-r</term>
<listitem>
<para>
Instead of running a new Asterisk process, attempt to connect
to a running Asterisk process and provide a console interface
for controlling it.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-R</term>
<listitem>
<para>
Much like <command>-r</command>. Instead of running a new Asterisk process, attempt to connect
to a running Asterisk process and provide a console interface
for controlling it. Additionally, if connection to the Asterisk
process is lost, attempt to reconnect for as long as 30 seconds.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-U <replaceable class="parameter">user</replaceable></term>
<listitem>
<para>
Run as user <replaceable>user</replaceable> instead of the
calling user. <command>NOTE:</command> this requires substantial work
to be sure that Asterisk's environment has permission to write
the files required for its operation, including logs, its comm
socket, the asterisk database, etc.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-v</term>
<listitem>
<para>
Increase the level of verboseness on the console. The more times
<command>-v</command> is specified, the more verbose the output is.
Specifying this option implies <command>-f</command> and will cause
asterisk to no longer fork or detach from the controlling terminal.
This option may also be used in conjunction with <command>-r</command>
and <command>-R</command>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-V</term>
<listitem>
<para>
Display version information and exit immediately.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-x <replaceable class="parameter">command</replaceable></term>
<listitem>
<para>
Connect to a running Asterisk process and execute a command on
a command line, passing any output through to standard out and
then terminating when the command execution completes. Implies
<command>-r</command> when <command>-R</command> is not explicitly
supplied.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>EXAMPLES</title>
<para>
<command>asterisk</command> - Begin Asterisk as a daemon
</para>
<para>
<command>asterisk -vvvgc</command> - Run on controlling terminal
</para>
<para>
<command>asterisk -rx "show channels"</command> - Display channels on running server
</para>
</refsect1>
<refsect1>
<title>BUGS</title>
<para>
Bug reports and feature requests may be filed at http://bugs.digium.com
</para>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>
*CLI&gt; <command>help</command> - Help on Asterisk CLI
</para>
<para>
*CLI&gt; <command>show applications</command> - Show loaded applications
</para>
<para>
http://www.asterisk.org - The Asterisk Home Page
</para>
<para>
http://www.asteriskdocs.org - The Asterisk Documentation Project
</para>
<para>
http://www.voip-info.org/wiki-Asterisk - The Asterisk Wiki
</para>
<para>
http://www.digium.com/ - Asterisk sponsor and hardware supplier
</para>
<para>
http://www.markocam.com/ - Asterisk author's web cam
</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>
<author>
<firstname>Mark Spencer &lt;markster@digium.com&gt;</firstname>
</author>
</para>
<para>
<author>
<firstname>Countless other contributers, see CREDITS with distribution for more information</firstname>
</author>
</para>
</refsect1>
</refentry>

View File

@@ -2,13 +2,7 @@
# Don't use ast mm routines
#
CFLAGS+=-DNO_AST_MM
OSARCH=$(shell uname -s)
ifeq ($(findstring BSD,${OSARCH}),BSD)
CFLAGS+=-I/usr/local/include -L/usr/local/lib
endif
TARGET=$(shell if [ -f /usr/include/newt.h ]; then echo "astman"; else if [ -f /usr/local/include/newt.h ]; then echo "astman"; else echo "none" ; fi ; fi)
TARGET=$(shell if [ -f /usr/include/newt.h ]; then echo "astman"; else echo "none" ; fi)
all: depend $(TARGET)
install:
@@ -25,7 +19,7 @@ clean:
rm -f *.o astman .depend
astman: astman.o ../md5.o
$(CC) $(CFLAGS) -o astman astman.o ../md5.o -lnewt
$(CC) -o astman astman.o ../md5.o -lnewt
ifneq ($(wildcard .depend),)
include .depend

View File

@@ -7,11 +7,11 @@
#include <newt.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <fcntl.h>
#include <string.h>
@@ -23,8 +23,6 @@
#include <asterisk/md5.h>
#include <asterisk/manager.h>
#undef gethostbyname
#define MAX_HEADERS 80
#define MAX_LEN 256
@@ -172,14 +170,13 @@ static struct event {
{ "Status", event_status },
{ "Link", event_ignore },
{ "Unlink", event_ignore },
{ "StatusComplete", event_ignore }
};
static int process_message(struct ast_mansession *s, struct message *m)
{
int x;
char event[80] = "";
strncpy(event, get_header(m, "Event"), sizeof(event) - 1);
char event[80];
strncpy(event, get_header(m, "Event"), sizeof(event));
if (!strlen(event)) {
fprintf(stderr, "Missing event in request");
return 0;
@@ -430,7 +427,7 @@ static int get_user_input(char *msg, char *buf, int buflen)
newtComponent ok;
newtComponent cancel;
newtComponent inpfield;
const char *input;
char *input;
int res = -1;
struct newtExitStruct es;
@@ -553,8 +550,8 @@ static int login(char *hostname)
newtComponent label;
newtComponent ulabel;
newtComponent plabel;
const char *user;
const char *pass;
char *user;
char *pass;
struct message *m;
struct newtExitStruct es;
char tmp[55];

View File

@@ -18,6 +18,7 @@
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <asterisk/cli.h>
#include <asterisk/logger.h>
@@ -57,8 +58,8 @@ static struct ast_region {
#define HASH(a) \
(((unsigned long)(a)) % SOME_PRIME)
AST_MUTEX_DEFINE_STATIC(reglock);
AST_MUTEX_DEFINE_STATIC(showmemorylock);
static ast_mutex_t reglock = AST_MUTEX_INITIALIZER;
static ast_mutex_t showmemorylock = AST_MUTEX_INITIALIZER;
static inline void *__ast_alloc_region(size_t size, int which, const char *file, int lineno, const char *func)
{

View File

@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
@@ -32,12 +33,10 @@
#include <asterisk/chanvars.h>
#include <asterisk/linkedlists.h>
#include <asterisk/indications.h>
#include <asterisk/lock.h>
#include <asterisk/utils.h>
#define MAX_AUTOMONS 256
AST_MUTEX_DEFINE_STATIC(autolock);
static ast_mutex_t autolock = AST_MUTEX_INITIALIZER;
struct asent {
struct ast_channel *chan;
@@ -45,7 +44,7 @@ struct asent {
};
static struct asent *aslist = NULL;
static pthread_t asthread = AST_PTHREADT_NULL;
static pthread_t asthread = (pthread_t) -1;
static void *autoservice_run(void *ign)
{
@@ -81,7 +80,7 @@ static void *autoservice_run(void *ign)
ast_frfree(f);
}
}
asthread = AST_PTHREADT_NULL;
asthread = (pthread_t) -1;
return NULL;
}
@@ -91,7 +90,7 @@ int ast_autoservice_start(struct ast_channel *chan)
struct asent *as;
int needstart;
ast_mutex_lock(&autolock);
needstart = (asthread == AST_PTHREADT_NULL) ? 1 : 0 /* aslist ? 0 : 1 */;
needstart = (asthread == (pthread_t) -1) ? 1 : 0 /* aslist ? 0 : 1 */;
as = aslist;
while(as) {
if (as->chan == chan)
@@ -107,7 +106,7 @@ int ast_autoservice_start(struct ast_channel *chan)
aslist = as;
res = 0;
if (needstart) {
if (ast_pthread_create(&asthread, NULL, autoservice_run, NULL)) {
if (pthread_create(&asthread, NULL, autoservice_run, NULL)) {
ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
free(aslist);
aslist = NULL;
@@ -143,7 +142,7 @@ int ast_autoservice_stop(struct ast_channel *chan)
if (!chan->_softhangup)
res = 0;
}
if (asthread != AST_PTHREADT_NULL)
if (asthread != (pthread_t) -1)
pthread_kill(asthread, SIGURG);
ast_mutex_unlock(&autolock);
/* Wait for it to un-block */

View File

@@ -3,9 +3,9 @@
*
* CallerID Generation support
*
* Copyright (C) 2001-2004, Digium, Inc.
* Copyright (C) 2001, Linux Support Services, Inc.
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License.
@@ -20,14 +20,12 @@
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <ctype.h>
#include <asterisk/ulaw.h>
#include <asterisk/alaw.h>
#include <asterisk/frame.h>
#include <asterisk/callerid.h>
#include <asterisk/logger.h>
#include <asterisk/fskmodem.h>
#include <asterisk/utils.h>
struct callerid_state {
fsk_data fskd;
@@ -74,7 +72,7 @@ static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1,
t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
*cr2 *= t;
*ci2 *= t;
buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
buf[x] = AST_LIN2X((*cr1 + *cr2) * 8192.0);
}
}
@@ -108,7 +106,7 @@ void callerid_init(void)
casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
}
struct callerid_state *callerid_new(int cid_signalling)
struct callerid_state *callerid_new(void)
{
struct callerid_state *cid;
cid = malloc(sizeof(struct callerid_state));
@@ -120,13 +118,8 @@ struct callerid_state *callerid_new(int cid_signalling)
cid->fskd.nstop = 1; /* 1 stop bit */
cid->fskd.paridad = 0; /* No parity */
cid->fskd.bw=1; /* Filter 800 Hz */
if (cid_signalling == 2) { /* v23 signalling */
cid->fskd.f_mark_idx = 4; /* 1300 Hz */
cid->fskd.f_space_idx = 5; /* 2100 Hz */
} else { /* Bell 202 signalling as default */
cid->fskd.f_mark_idx = 2; /* 1200 Hz */
cid->fskd.f_space_idx = 3; /* 2200 Hz */
}
cid->fskd.f_mark_idx = 2; /* 1200 Hz */
cid->fskd.f_space_idx = 3; /* 2200 Hz */
cid->fskd.pcola = 0; /* No clue */
cid->fskd.cont = 0; /* Digital PLL reset */
cid->fskd.x0 = 0.0;
@@ -153,67 +146,6 @@ void callerid_get(struct callerid_state *cid, char **name, char **number, int *f
*number = cid->number;
}
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
{
int i;
int code;
/* "Clear" the number-buffer. */
number[0] = 0;
if (strlen(cidstring) < 2) {
ast_log(LOG_DEBUG, "No cid detected\n");
*flags = CID_UNKNOWN_NUMBER;
return;
}
/* Detect protocol and special types */
if (cidstring[0] == 'B') {
/* Handle special codes */
code = atoi(&cidstring[1]);
if (code == 0)
*flags = CID_UNKNOWN_NUMBER;
else if (code == 10)
*flags = CID_PRIVATE_NUMBER;
else
ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code);
} else if (cidstring[0] == 'D' && cidstring[2] == '#') {
/* .DK special code */
if (cidstring[1] == '1')
*flags = CID_PRIVATE_NUMBER;
if (cidstring[1] == '2' || cidstring[1] == '3')
*flags = CID_UNKNOWN_NUMBER;
} else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
/* "Standard" callerid */
for (i = 1; i < strlen(cidstring); i++ ) {
if (cidstring[i] == 'C' || cidstring[i] == '#')
break;
if (isdigit(cidstring[i]))
number[i-1] = cidstring[i];
else
ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
cidstring[i]);
}
number[i-1] = 0;
} else if (isdigit(cidstring[0])) {
/* It begins with a digit, so we parse it as a number and hope
* for the best */
ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
"parsing might be unreliable\n");
for (i = 0; i < strlen(cidstring); i++) {
if (isdigit(cidstring[i]))
number[i] = cidstring[i];
else
break;
}
number[i] = 0;
} else {
ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n",
cidstring[0]);
*flags = CID_UNKNOWN_NUMBER;
}
}
int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
{
int pos = 0;
@@ -253,7 +185,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
mylen += cid->oldlen/2;
for (x=0;x<len;x++)
buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
while(mylen >= 160) {
while(mylen >= 80) {
olen = mylen;
res = fsk_serie(&cid->fskd, buf, &mylen, &b);
if (mylen < 0) {
@@ -309,8 +241,8 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
break;
}
cid->number[0] = '\0';
cid->name[0] = '\0';
strcpy(cid->number, "");
strcpy(cid->name, "");
/* If we get this far we're fine. */
if (cid->type == 0x80) {
/* MDMF */
@@ -328,13 +260,9 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
res = 32;
}
if (ast_strlen_zero(cid->number)) {
memcpy(cid->number, cid->rawdata + x + 1, res);
/* Null terminate */
cid->number[res] = '\0';
}
break;
case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
memcpy(cid->number, cid->rawdata + x + 1, res);
/* Null terminate */
cid->number[res] = '\0';
break;
case 7: /* Name */
case 8: /* Name */
@@ -346,8 +274,6 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
memcpy(cid->name, cid->rawdata + x + 1, res);
cid->name[res] = '\0';
break;
case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
case 19: /* UK: Network message system status (Number of messages waiting) */
case 22: /* Something French */
break;
default:
@@ -365,14 +291,14 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int
if (!strcmp(cid->number, "P")) {
strcpy(cid->number, "");
cid->flags |= CID_PRIVATE_NUMBER;
} else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
} else if (!strcmp(cid->number, "O") || !strlen(cid->number)) {
strcpy(cid->number, "");
cid->flags |= CID_UNKNOWN_NUMBER;
}
if (!strcmp(cid->name, "P")) {
strcpy(cid->name, "");
cid->flags |= CID_PRIVATE_NAME;
} else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
} else if (!strcmp(cid->name, "O") || !strlen(cid->name)) {
strcpy(cid->name, "");
cid->flags |= CID_UNKNOWN_NAME;
}
@@ -415,7 +341,7 @@ static int callerid_genmsg(char *msg, int size, char *number, char *name, int fl
tm.tm_mday, tm.tm_hour, tm.tm_min);
size -= res;
ptr += res;
if (!number || ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
if (!number || !strlen(number) || (flags & CID_UNKNOWN_NUMBER)) {
/* Indicate number not known */
res = snprintf(ptr, size, "\004\001O");
size -= res;
@@ -439,7 +365,7 @@ static int callerid_genmsg(char *msg, int size, char *number, char *name, int fl
size -= i;
}
if (!name || ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
if (!name || !strlen(name) || (flags & CID_UNKNOWN_NAME)) {
/* Indicate name not known */
res = snprintf(ptr, size, "\010\001O");
size -= res;
@@ -510,9 +436,6 @@ int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
sum += msg[x];
sum = (256 - (sum & 255));
msg[len++] = sum;
/* Wait a half a second */
for (x=0;x<4000;x++)
PUT_BYTE(0x7f);
/* Transmit 30 0x55's (looks like a square wave) for channel seizure */
for (x=0;x<30;x++)
PUT_CLID(0x55);
@@ -582,10 +505,10 @@ void ast_shrink_phone_number(char *n)
int ast_isphonenumber(char *n)
{
int x;
if (!n || ast_strlen_zero(n))
if (!n || !strlen(n))
return 0;
for (x=0;n[x];x++)
if (!strchr("0123456789*#+", n[x]))
if (!strchr("0123456789*#", n[x]))
return 0;
return 1;
}
@@ -611,7 +534,7 @@ int ast_callerid_parse(char *instr, char **name, char **location)
} else {
/* Just trim off any trailing spaces */
*name = instr;
while(!ast_strlen_zero(instr) && (instr[strlen(instr) - 1] < 33))
while(strlen(instr) && (instr[strlen(instr) - 1] < 33))
instr[strlen(instr) - 1] = '\0';
/* And leading spaces */
while(**name && (**name < 33))

354
cdr.c
View File

@@ -3,9 +3,9 @@
*
* Call Detail Record API
*
* Copyright (C) 1999-2004, Digium, Inc.
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@digium.com>
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License.
@@ -20,16 +20,15 @@
#include <asterisk/logger.h>
#include <asterisk/callerid.h>
#include <asterisk/causes.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
int ast_default_amaflags = AST_CDR_DOCUMENTATION;
char ast_default_accountcode[20] = "";
AST_MUTEX_DEFINE_STATIC(cdrlock);
static ast_mutex_t cdrlock = AST_MUTEX_INITIALIZER;
static struct ast_cdr_beitem {
char name[20];
@@ -38,7 +37,6 @@ static struct ast_cdr_beitem {
struct ast_cdr_beitem *next;
} *bes = NULL;
/*
* We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip
* through our fingers somehow. If someone allocates a CDR, it must be completely handled normally
@@ -96,8 +94,6 @@ void ast_cdr_unregister(char *name)
}
i = i->next;
}
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name);
ast_mutex_unlock(&cdrlock);
if (i)
free(i);
@@ -105,19 +101,16 @@ void ast_cdr_unregister(char *name)
void ast_cdr_free(struct ast_cdr *cdr)
{
char *chan;
struct ast_cdr *next;
while (cdr) {
next = cdr->next;
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (!ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
char *chan;
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (!cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
free(cdr);
cdr = next;
}
}
@@ -134,67 +127,58 @@ struct ast_cdr *ast_cdr_alloc(void)
void ast_cdr_start(struct ast_cdr *cdr)
{
char *chan;
while (cdr) {
if (!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (cdr->start.tv_sec || cdr->start.tv_usec)
ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
gettimeofday(&cdr->start, NULL);
}
cdr = cdr->next;
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (cdr->start.tv_sec || cdr->start.tv_usec)
ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
gettimeofday(&cdr->start, NULL);
}
}
void ast_cdr_answer(struct ast_cdr *cdr)
{
char *chan;
while (cdr) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (cdr->disposition < AST_CDR_ANSWERED)
cdr->disposition = AST_CDR_ANSWERED;
if (!cdr->answer.tv_sec && !cdr->answer.tv_usec) {
gettimeofday(&cdr->answer, NULL);
}
cdr = cdr->next;
}
}
void ast_cdr_busy(struct ast_cdr *cdr)
{
char *chan;
while (cdr) {
if (!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (cdr->disposition < AST_CDR_BUSY)
cdr->disposition = AST_CDR_BUSY;
}
cdr = cdr->next;
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (cdr->disposition < AST_CDR_BUSY)
cdr->disposition = AST_CDR_BUSY;
}
}
void ast_cdr_failed(struct ast_cdr *cdr)
{
char *chan;
while (cdr) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
cdr->disposition = AST_CDR_FAILED;
cdr = cdr->next;
}
}
int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
{
int res = 0;
while (cdr) {
if (cdr) {
switch(cause) {
case AST_CAUSE_BUSY:
ast_cdr_busy(cdr);
@@ -211,7 +195,6 @@ int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
res = -1;
ast_log(LOG_WARNING, "We don't handle that cause yet\n");
}
cdr = cdr->next;
}
return res;
}
@@ -219,32 +202,27 @@ int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
void ast_cdr_setdestchan(struct ast_cdr *cdr, char *chann)
{
char *chan;
while (cdr) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
strncpy(cdr->dstchannel, chann, sizeof(cdr->dstchannel) - 1);
cdr = cdr->next;
strncpy(cdr->dstchannel, chann, sizeof(cdr->dstchannel) - 1);
}
}
void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
{
char *chan;
while (cdr) {
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (!app)
app = "";
strncpy(cdr->lastapp, app, sizeof(cdr->lastapp) - 1);
if (!data)
data = "";
strncpy(cdr->lastdata, data, sizeof(cdr->lastdata) - 1);
}
cdr = cdr->next;
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (!app)
app = "";
strncpy(cdr->lastapp, app, sizeof(cdr->lastapp) - 1);
if (!data)
data = "";
strncpy(cdr->lastdata, data, sizeof(cdr->lastdata) - 1);
}
}
@@ -252,24 +230,21 @@ int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
{
char tmp[AST_MAX_EXTENSION] = "";
char *num, *name;
while (cdr) {
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
/* Grab source from ANI or normal Caller*ID */
if (c->ani)
strncpy(tmp, c->ani, sizeof(tmp) - 1);
else if (c->callerid)
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
if (c->callerid)
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
name = NULL;
num = NULL;
ast_callerid_parse(tmp, &name, &num);
if (num) {
ast_shrink_phone_number(num);
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
}
if (cdr) {
/* Grab source from ANI or normal Caller*ID */
if (c->ani)
strncpy(tmp, c->ani, sizeof(tmp) - 1);
else if (c->callerid)
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
if (c->callerid)
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
name = NULL;
num = NULL;
ast_callerid_parse(tmp, &name, &num);
if (num) {
ast_shrink_phone_number(num);
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
}
cdr = cdr->next;
}
return 0;
}
@@ -279,43 +254,40 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
char *chan;
char *num, *name;
char tmp[AST_MAX_EXTENSION] = "";
while (cdr) {
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (!ast_strlen_zero(cdr->channel))
ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
strncpy(cdr->channel, c->name, sizeof(cdr->channel) - 1);
/* Grab source from ANI or normal Caller*ID */
if (c->ani)
strncpy(tmp, c->ani, sizeof(tmp) - 1);
else if (c->callerid)
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
if (c->callerid)
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
name = NULL;
num = NULL;
ast_callerid_parse(tmp, &name, &num);
if (num) {
ast_shrink_phone_number(num);
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
}
if (c->_state == AST_STATE_UP)
cdr->disposition = AST_CDR_ANSWERED;
else
cdr->disposition = AST_CDR_NOANSWER;
if (c->amaflags)
cdr->amaflags = c->amaflags;
else
cdr->amaflags = ast_default_amaflags;
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
/* Destination information */
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
/* Unique call identifier */
strncpy(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid) - 1);
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (strlen(cdr->channel))
ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
strncpy(cdr->channel, c->name, sizeof(cdr->channel) - 1);
/* Grab source from ANI or normal Caller*ID */
if (c->ani)
strncpy(tmp, c->ani, sizeof(tmp) - 1);
else if (c->callerid)
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
if (c->callerid)
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
name = NULL;
num = NULL;
ast_callerid_parse(tmp, &name, &num);
if (num) {
ast_shrink_phone_number(num);
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
}
cdr = cdr->next;
if (c->_state == AST_STATE_UP)
cdr->disposition = AST_CDR_ANSWERED;
else
cdr->disposition = AST_CDR_NOANSWER;
if (c->amaflags)
cdr->amaflags = c->amaflags;
else
cdr->amaflags = ast_default_amaflags;
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
/* Destination information */
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
/* Unique call identifier */
strncpy(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid) - 1);
}
return 0;
}
@@ -323,15 +295,14 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
void ast_cdr_end(struct ast_cdr *cdr)
{
char *chan;
while (cdr) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (!cdr->start.tv_sec && !cdr->start.tv_usec)
ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
gettimeofday(&cdr->end, NULL);
cdr = cdr->next;
}
}
@@ -369,23 +340,8 @@ int ast_cdr_setaccount(struct ast_channel *chan, char *account)
struct ast_cdr *cdr = chan->cdr;
strncpy(chan->accountcode, account, sizeof(chan->accountcode) - 1);
while (cdr) {
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
strncpy(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode) - 1);
cdr = cdr->next;
}
return 0;
}
int ast_cdr_setamaflags(struct ast_channel *chan, char *flag)
{
struct ast_cdr *cdr = chan->cdr;
int newflag;
newflag = ast_cdr_amaflags2int(flag);
if (newflag) {
cdr->amaflags = newflag;
}
if (cdr)
strncpy(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode) - 1);
return 0;
}
@@ -393,11 +349,8 @@ int ast_cdr_setuserfield(struct ast_channel *chan, char *userfield)
{
struct ast_cdr *cdr = chan->cdr;
while (cdr) {
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
strncpy(cdr->userfield, userfield, sizeof(cdr->userfield) - 1);
cdr = cdr->next;
}
if (cdr)
strncpy(cdr->userfield, userfield, sizeof(cdr->userfield) - 1);
return 0;
}
@@ -405,13 +358,10 @@ int ast_cdr_appenduserfield(struct ast_channel *chan, char *userfield)
{
struct ast_cdr *cdr = chan->cdr;
while (cdr)
if (cdr)
{
int len = strlen(cdr->userfield);
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED))
strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
cdr = cdr->next;
strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
}
return 0;
}
@@ -422,38 +372,28 @@ int ast_cdr_update(struct ast_channel *c)
char *name, *num;
char tmp[AST_MAX_EXTENSION] = "";
/* Grab source from ANI or normal Caller*ID */
while (cdr) {
if(!ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
if (c->ani)
strncpy(tmp, c->ani, sizeof(tmp) - 1);
else if (c->callerid && !ast_strlen_zero(c->callerid))
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
if (c->callerid && !ast_strlen_zero(c->callerid))
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
else
cdr->clid[0] = '\0';
name = NULL;
num = NULL;
ast_callerid_parse(tmp, &name, &num);
if (num) {
ast_shrink_phone_number(num);
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
}
/* Copy account code et-al */
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
/* Destination information */
if (ast_strlen_zero(c->macroexten))
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
else
strncpy(cdr->dst, c->macroexten, sizeof(cdr->dst) - 1);
if (ast_strlen_zero(c->macrocontext))
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
else
strncpy(cdr->dcontext, c->macrocontext, sizeof(cdr->dcontext) - 1);
if (cdr) {
if (c->ani)
strncpy(tmp, c->ani, sizeof(tmp) - 1);
else if (c->callerid && strlen(c->callerid))
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
if (c->callerid && strlen(c->callerid))
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
else
strcpy(cdr->clid, "");
name = NULL;
num = NULL;
ast_callerid_parse(tmp, &name, &num);
if (num) {
ast_shrink_phone_number(num);
strncpy(cdr->src, num, sizeof(cdr->src) - 1);
}
cdr = cdr->next;
/* Copy account code et-al */
strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
/* Destination information */
strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
}
return 0;
}
@@ -474,9 +414,9 @@ void ast_cdr_post(struct ast_cdr *cdr)
{
char *chan;
struct ast_cdr_beitem *i;
while (cdr) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_cdr_has_flag(cdr,AST_CDR_FLAG_POSTED))
if (cdr) {
chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
if (cdr->posted)
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
if (!cdr->end.tv_sec && !cdr->end.tv_usec)
ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
@@ -487,7 +427,7 @@ void ast_cdr_post(struct ast_cdr *cdr)
cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000;
} else
cdr->billsec = 0;
ast_cdr_add_flag(cdr,AST_CDR_FLAG_POSTED);
cdr->posted = 1;
ast_mutex_lock(&cdrlock);
i = bes;
while(i) {
@@ -495,45 +435,25 @@ void ast_cdr_post(struct ast_cdr *cdr)
i = i->next;
}
ast_mutex_unlock(&cdrlock);
cdr = cdr->next;
}
}
void ast_cdr_reset(struct ast_cdr *cdr, int flags)
void ast_cdr_reset(struct ast_cdr *cdr, int post)
{
while (cdr) {
/* Post if requested */
if (ast_cdr_compare_flag(flags,AST_CDR_FLAG_LOCKED) || !ast_cdr_has_flag(cdr,AST_CDR_FLAG_LOCKED)) {
if (ast_cdr_compare_flag(flags,AST_CDR_FLAG_POSTED)) {
ast_cdr_end(cdr);
ast_cdr_post(cdr);
}
/* Reset to initial state */
cdr->flags=0;
memset(&cdr->start, 0, sizeof(cdr->start));
memset(&cdr->end, 0, sizeof(cdr->end));
memset(&cdr->answer, 0, sizeof(cdr->answer));
cdr->billsec = 0;
cdr->duration = 0;
ast_cdr_start(cdr);
cdr->disposition = AST_CDR_NOANSWER;
}
cdr = cdr->next;
}
}
struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr)
{
struct ast_cdr *ret;
if (cdr) {
ret = cdr;
while(cdr->next)
cdr = cdr->next;
cdr->next = newcdr;
} else {
ret = newcdr;
/* Post if requested */
if (post) {
ast_cdr_end(cdr);
ast_cdr_post(cdr);
}
/* Reset to initial state */
cdr->posted = 0;
memset(&cdr->start, 0, sizeof(cdr->start));
memset(&cdr->end, 0, sizeof(cdr->end));
memset(&cdr->answer, 0, sizeof(cdr->answer));
cdr->billsec = 0;
cdr->duration = 0;
ast_cdr_start(cdr);
cdr->disposition = AST_CDR_NOANSWER;
}
return ret;
}

View File

@@ -12,40 +12,17 @@
#
#ADD cdr_pgsql.so to MODS= to include PostgreSQL support: REQUIRES PostgreSQL libs
MODS=cdr_csv.so cdr_manager.so
MODS=cdr_csv.so
CFLAGS+=-fPIC
PROC=$(shell uname -m)
OSARCH=$(shell uname -s)
ifeq (${OSARCH},FreeBSD)
SOLINK+=-L/usr/local/lib
endif
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
#This works for even old (2.96) versions of gcc and provides a small boost either way.
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn.t support it.
#So we go lowest common available by gcc and go a step down, still a step up from
#the default as we now have a better instruction set to work with. - Belgarath
ifeq ($(PROC),sparc64)
PROC=ultrasparc
CFLAGS += -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
endif
#
# unixODBC stuff...
#
MODS+=$(shell if [ -f "/usr/include/odbcinst.h" ]; then echo "cdr_odbc.so"; fi)
MODS+=$(shell if [ -f "/usr/local/include/odbcinst.h" ]; then echo "cdr_odbc.so"; fi)
#
# FreeTDS stuff...
#
MODS+=$(shell if [ -f "/usr/include/tds.h" ]; then echo "cdr_tds.so"; fi)
MODS+=$(shell if [ -f "/usr/local/include/tds.h" ]; then echo "cdr_tds.so"; fi)
#
# PGSQL stuff... Autoconf anyone??
#
@@ -55,7 +32,7 @@ CFLAGS+=$(shell if [ -d /usr/include/pgsql ]; then echo "-I/usr/include/pgsql";
CFLAGS+=$(shell if [ -d /usr/include/postgresql ]; then echo "-I/usr/include/postgresql"; fi)
CFLAGS+=$(shell if [ -d /usr/local/include/pgsql ]; then echo "-I/usr/local/include/pgsql"; fi)
CFLAGS+=$(shell if [ -d /opt/pgsql/include ]; then echo "-I/opt/pgsql/include"; fi)
#CFLAGS+=$(shell if [ -f /usr/include/libpq-fe.h ]; then echo "-I/usr/include"; fi)
CFLAGS+=$(shell if [ -f /usr/include/libpq-fe.h ]; then echo "-I/usr/include"; fi)
MLFLAGS=
MLFLAGS+=$(shell if [ -d /usr/lib/pgsql ]; then echo "-L/usr/lib/pgsql"; fi)
MLFLAGS+=$(shell if [ -d /usr/local/pgsql/lib ]; then echo "-L/usr/local/pgsql/lib"; fi)
@@ -63,11 +40,6 @@ MLFLAGS+=$(shell if [ -d /usr/local/lib/pgsql ]; then echo "-L/usr/local/lib/pgs
MLFLAGS+=$(shell if [ -d /opt/pgsql/lib ]; then echo "-L/opt/pgsql/lib"; fi)
MLFLAGS+=$(shell if [ -f /usr/lib/libpq.so ]; then echo "-L/usr/lib"; fi)
#
# SQLIte stuff...
#
MODS+=$(shell if [ -f "/usr/include/sqlite.h" ]; then echo "cdr_sqlite.so"; fi)
all: depend $(MODS)
install: all
@@ -86,15 +58,9 @@ endif
cdr_odbc.so: cdr_odbc.o
$(CC) $(SOLINK) -o $@ $< -lodbc $(MLFLAGS)
cdr_tds.so: cdr_tds.o
$(CC) $(SOLINK) -o $@ $< -ltds $(MLFLAGS)
cdr_pgsql.so: cdr_pgsql.o
$(CC) $(SOLINK) -o $@ $< -lpq -lz $(MLFLAGS)
cdr_sqlite.so: cdr_sqlite.o
$(CC) $(SOLINK) -o $@ $< -lsqlite $(MLFLAGS)
depend: .depend
.depend:

View File

@@ -19,7 +19,6 @@
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include <asterisk/utils.h>
#include "../asterisk.h"
#include "../astconf.h"
@@ -33,7 +32,6 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
@@ -72,16 +70,16 @@ static char *name = "csv";
static FILE *mf = NULL;
static int append_string(char *buf, char *s, size_t bufsize)
static int append_string(char *buf, char *s, int len)
{
int pos = strlen(buf);
int spos = 0;
int error = 0;
if (pos >= bufsize - 4)
if (pos >= len - 4)
return -1;
buf[pos++] = '\"';
error = -1;
while(pos < bufsize - 3) {
while(pos < len - 3) {
if (!s[spos]) {
error = 0;
break;
@@ -97,87 +95,87 @@ static int append_string(char *buf, char *s, size_t bufsize)
return error;
}
static int append_int(char *buf, int s, size_t bufsize)
static int append_int(char *buf, int s, int len)
{
char tmp[32];
int pos = strlen(buf);
snprintf(tmp, sizeof(tmp), "%d", s);
if (pos + strlen(tmp) > bufsize - 3)
if (pos + strlen(tmp) > len - 3)
return -1;
strncat(buf, tmp, bufsize - strlen(buf) - 1);
strncat(buf, tmp, len);
pos = strlen(buf);
buf[pos++] = ',';
buf[pos++] = '\0';
return 0;
}
static int append_date(char *buf, struct timeval tv, size_t bufsize)
static int append_date(char *buf, struct timeval tv, int len)
{
char tmp[80] = "";
char tmp[80];
struct tm tm;
time_t t;
t = tv.tv_sec;
if (strlen(buf) > bufsize - 3)
if (strlen(buf) > len - 3)
return -1;
if (!tv.tv_sec && !tv.tv_usec) {
strncat(buf, ",", bufsize - strlen(buf) - 1);
strncat(buf, ",", len);
return 0;
}
localtime_r(&t,&tm);
strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm);
return append_string(buf, tmp, bufsize);
return append_string(buf, tmp, len);
}
static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr)
static int build_csv_record(char *buf, int len, struct ast_cdr *cdr)
{
buf[0] = '\0';
/* Account code */
append_string(buf, cdr->accountcode, bufsize);
append_string(buf, cdr->accountcode, len);
/* Source */
append_string(buf, cdr->src, bufsize);
append_string(buf, cdr->src, len);
/* Destination */
append_string(buf, cdr->dst, bufsize);
append_string(buf, cdr->dst, len);
/* Destination context */
append_string(buf, cdr->dcontext, bufsize);
append_string(buf, cdr->dcontext, len);
/* Caller*ID */
append_string(buf, cdr->clid, bufsize);
append_string(buf, cdr->clid, len);
/* Channel */
append_string(buf, cdr->channel, bufsize);
append_string(buf, cdr->channel, len);
/* Destination Channel */
append_string(buf, cdr->dstchannel, bufsize);
append_string(buf, cdr->dstchannel, len);
/* Last Application */
append_string(buf, cdr->lastapp, bufsize);
append_string(buf, cdr->lastapp, len);
/* Last Data */
append_string(buf, cdr->lastdata, bufsize);
append_string(buf, cdr->lastdata, len);
/* Start Time */
append_date(buf, cdr->start, bufsize);
append_date(buf, cdr->start, len);
/* Answer Time */
append_date(buf, cdr->answer, bufsize);
append_date(buf, cdr->answer, len);
/* End Time */
append_date(buf, cdr->end, bufsize);
append_date(buf, cdr->end, len);
/* Duration */
append_int(buf, cdr->duration, bufsize);
append_int(buf, cdr->duration, len);
/* Billable seconds */
append_int(buf, cdr->billsec, bufsize);
append_int(buf, cdr->billsec, len);
/* Disposition */
append_string(buf, ast_cdr_disp2str(cdr->disposition), bufsize);
append_string(buf, ast_cdr_disp2str(cdr->disposition), len);
/* AMA Flags */
append_string(buf, ast_cdr_flags2str(cdr->amaflags), bufsize);
append_string(buf, ast_cdr_flags2str(cdr->amaflags), len);
#ifdef CSV_LOGUNIQUEID
/* Unique ID */
append_string(buf, cdr->uniqueid, bufsize);
append_string(buf, cdr->uniqueid, len);
#endif
#ifdef CSV_LOGUSERFIELD
/* append the user field */
append_string(buf, cdr->userfield,bufsize);
append_string(buf, cdr->userfield,len);
#endif
/* If we hit the end of our buffer, log an error */
if (strlen(buf) < bufsize - 5) {
if (strlen(buf) < len - 5) {
/* Trim off trailing comma */
buf[strlen(buf) - 1] = '\0';
strncat(buf, "\n", bufsize - strlen(buf) - 1);
strncat(buf, "\n", len);
return 0;
}
return -1;
@@ -185,7 +183,7 @@ static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr)
static int writefile(char *s, char *acc)
{
char tmp[AST_CONFIG_MAX_PATH];
char tmp[256];
FILE *f;
if (strchr(acc, '/') || (acc[0] == '.')) {
ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
@@ -196,7 +194,6 @@ static int writefile(char *s, char *acc)
if (!f)
return -1;
fputs(s, f);
fflush(f);
fclose(f);
return 0;
}
@@ -207,19 +204,19 @@ static int csv_log(struct ast_cdr *cdr)
/* Make sure we have a big enough buf */
char buf[1024];
char csvmaster[AST_CONFIG_MAX_PATH];
snprintf(csvmaster, sizeof(csvmaster),"%s/%s/%s", ast_config_AST_LOG_DIR, CSV_LOG_DIR, CSV_MASTER);
snprintf((char *)csvmaster,sizeof(csvmaster)-1,"%s/%s/%s",(char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR,CSV_MASTER);
#if 0
printf("[CDR] %s ('%s' -> '%s') Dur: %ds Bill: %ds Disp: %s Flags: %s Account: [%s]\n", cdr->channel, cdr->src, cdr->dst, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), cdr->accountcode);
#endif
if (build_csv_record(buf, sizeof(buf), cdr)) {
ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes. CDR not recorded!\n", (int)sizeof(buf));
ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes. CDR not recorded!\n", sizeof(buf));
} else {
/* because of the absolutely unconditional need for the
highest reliability possible in writing billing records,
we open write and close the log file each time */
mf = fopen(csvmaster, "a");
if (!mf) {
ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
ast_log(LOG_ERROR, "Unable to re-open master file %s\n", csvmaster);
}
if (mf) {
fputs(buf, mf);
@@ -227,9 +224,9 @@ static int csv_log(struct ast_cdr *cdr)
fclose(mf);
mf = NULL;
}
if (!ast_strlen_zero(cdr->accountcode)) {
if (strlen(cdr->accountcode)) {
if (writefile(buf, cdr->accountcode))
ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno));
ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s'\n", cdr->accountcode);
}
}
return 0;

View File

@@ -1,158 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Asterisk Call Manager CDR records.
*
* This program is free software, distributed under the terms of
* the GNU General Public License.
*
*/
#include <sys/types.h>
#include <asterisk/channel.h>
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include <asterisk/utils.h>
#include <asterisk/manager.h>
#include <asterisk/config.h>
#include "../asterisk.h"
#include "../astconf.h"
#include <strings.h>
#include <unistd.h>
#include <time.h>
#define DATE_FORMAT "%Y-%m-%d %T"
#define CONF_FILE "cdr_manager.conf"
static char *desc = "Asterisk Call Manager CDR Backend";
static char *name = "cdr_as";
static int enablecdr = 0;
static void loadconfigurationfile(void)
{
char *cat;
struct ast_config *cfg;
struct ast_variable *v;
cfg = ast_load(CONF_FILE);
if (!cfg) {
/* Standard configuration */
enablecdr = 0;
return;
}
cat = ast_category_browse(cfg, NULL);
while (cat) {
if (!strcasecmp(cat, "general")) {
v = ast_variable_browse(cfg, cat);
while (v) {
if (!strcasecmp(v->name, "enabled")) {
enablecdr = ast_true(v->value);
}
v = v->next;
}
}
/* Next category */
cat = ast_category_browse(cfg, cat);
}
ast_destroy(cfg);
}
static int manager_log(struct ast_cdr *cdr)
{
time_t t;
struct tm timeresult;
char strStartTime[80] = "";
char strAnswerTime[80] = "";
char strEndTime[80] = "";
if (!enablecdr)
return 0;
t = cdr->start.tv_sec;
localtime_r(&t, &timeresult);
strftime(strStartTime, sizeof(strStartTime), DATE_FORMAT, &timeresult);
if (cdr->answer.tv_sec) {
t = cdr->answer.tv_sec;
localtime_r(&t, &timeresult);
strftime(strAnswerTime, sizeof(strAnswerTime), DATE_FORMAT, &timeresult);
}
t = cdr->end.tv_sec;
localtime_r(&t, &timeresult);
strftime(strEndTime, sizeof(strEndTime), DATE_FORMAT, &timeresult);
manager_event(EVENT_FLAG_CALL, "Cdr",
"AccountCode: %s\r\n"
"Source: %s\r\n"
"Destination: %s\r\n"
"DestinationContext: %s\r\n"
"CallerID: %s\r\n"
"Channel: %s\r\n"
"DestinationChannel: %s\r\n"
"LastApplication: %s\r\n"
"LastData: %s\r\n"
"StartTime: %s\r\n"
"AnswerTime: %s\r\n"
"EndTime: %s\r\n"
"Duration: %d\r\n"
"BillableSeconds: %d\r\n"
"Disposition: %s\r\n"
"AMAFlags: %s\r\n"
"UniqueID: %s\r\n"
"UserField: %s\r\n",
cdr->accountcode, cdr->src, cdr->dst, cdr->dcontext, cdr->clid, cdr->channel,
cdr->dstchannel, cdr->lastapp, cdr->lastdata, strStartTime, strAnswerTime, strEndTime,
cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition),
ast_cdr_flags2str(cdr->amaflags), cdr->uniqueid, cdr->userfield);
return 0;
}
char *description(void)
{
return desc;
}
int unload_module(void)
{
ast_cdr_unregister(name);
return 0;
}
int load_module(void)
{
int res;
/* Configuration file */
loadconfigurationfile();
res = ast_cdr_register(name, desc, manager_log);
if (res) {
ast_log(LOG_ERROR, "Unable to register Asterisk Call Manager CDR handling\n");
}
return res;
}
int reload(void)
{
loadconfigurationfile();
return 0;
}
int usecount(void)
{
return 0;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -3,12 +3,13 @@
*
* ODBC CDR Backend
*
* Copyright (C) 2003-2005, Digium, Inc.
*
* Brian K. West <brian@bkw.org>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
* the GNU General Public License.
*
* Copyright (c) 2003 Digium, Inc.
*
*/
#include <sys/types.h>
@@ -36,12 +37,11 @@
static char *desc = "ODBC CDR Backend";
static char *name = "ODBC";
static char *config = "cdr_odbc.conf";
static char *dsn = NULL, *username = NULL, *password = NULL;
static int dsn_alloc = 0, username_alloc = 0, password_alloc = 0;
static int loguniqueid = 0;
static char *dsn = NULL, *username = NULL, *password = NULL, *loguniqueid = NULL;
static int dsn_alloc = 0, username_alloc = 0, password_alloc = 0, loguniqueid_alloc = 0;
static int connected = 0;
AST_MUTEX_DEFINE_STATIC(odbc_lock);
static ast_mutex_t odbc_lock = AST_MUTEX_INITIALIZER;
static int odbc_do_query(void);
static int odbc_init(void);
@@ -56,40 +56,51 @@ static int odbc_log(struct ast_cdr *cdr)
short int ODBC_mlen;
int ODBC_res;
char ODBC_msg[200], ODBC_stat[10];
char sqlcmd[2048] = "", timestr[128];
char sqlcmd[2048], timestr[128];
int res = 0;
struct tm tm;
struct timeval tv;
time_t t;
localtime_r(&cdr->start.tv_sec,&tm);
gettimeofday(&tv,NULL);
t = tv.tv_sec;
localtime_r(&t,&tm);
ast_mutex_lock(&odbc_lock);
strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
strftime(timestr,128,DATE_FORMAT,&tm);
memset(sqlcmd,0,2048);
if (loguniqueid) {
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr "
if((loguniqueid != NULL) && ((strcmp(loguniqueid, "1") == 0) || (strcmp(loguniqueid, "yes") == 0)))
{
sprintf(sqlcmd,"INSERT INTO cdr "
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
"lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
} else {
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr "
}
else
{
sprintf(sqlcmd,"INSERT INTO cdr "
"(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
"duration,billsec,disposition,amaflags,accountcode) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
}
if (!connected) {
res = odbc_init();
if (res < 0) {
if(!connected)
{
res = odbc_init();
if(res < 0)
{
connected = 0;
ast_mutex_unlock(&odbc_lock);
return 0;
}
}
ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, ODBC_con, &ODBC_stmt);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
if (option_verbose > 10)
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Failure in AllocStatement %d\n", ODBC_res);
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
@@ -104,8 +115,9 @@ static int odbc_log(struct ast_cdr *cdr)
ODBC_res = SQLPrepare(ODBC_stmt, sqlcmd, SQL_NTS);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
if (option_verbose > 10)
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in PREPARE %d\n", ODBC_res);
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
@@ -114,53 +126,61 @@ static int odbc_log(struct ast_cdr *cdr)
return 0;
}
SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(timestr), 0, &timestr, 0, NULL);
SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->clid), 0, cdr->clid, 0, NULL);
SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->src), 0, cdr->src, 0, NULL);
SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dst), 0, cdr->dst, 0, NULL);
SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dcontext), 0, cdr->dcontext, 0, NULL);
SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->channel), 0, cdr->channel, 0, NULL);
SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL);
SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, &timestr, 0, NULL);
SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->clid, 0, NULL);
SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->src, 0, NULL);
SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dst, 0, NULL);
SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dcontext, 0, NULL);
SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->channel, 0, NULL);
SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->dstchannel, 0, NULL);
SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->lastapp, 0, NULL);
SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->lastdata, 0, NULL);
SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->accountcode, 0, NULL);
if (loguniqueid) {
SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL);
if((loguniqueid != NULL) && ((strcmp(loguniqueid, "1") == 0) || (strcmp(loguniqueid, "yes") == 0)))
{
SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->uniqueid, 0, NULL);
SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, cdr->userfield, 0, NULL);
}
if (connected) {
if(connected)
{
res = odbc_do_query();
if (res < 0) {
if (option_verbose > 10)
if(res < 0)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
res = odbc_init();
if (option_verbose > 10)
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Reconnecting to dsn %s\n", dsn);
if (res < 0) {
if (option_verbose > 10)
if(res < 0)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: %s has gone away!\n", dsn);
connected = 0;
} else {
if (option_verbose > 10)
}
else
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Trying Query again!\n");
res = odbc_do_query();
if (res < 0) {
if (option_verbose > 10)
if(res < 0)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
}
}
}
} else {
if (option_verbose > 10)
}
else
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
}
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
ast_mutex_unlock(&odbc_lock);
return 0;
}
@@ -173,8 +193,9 @@ char *description(void)
static int odbc_unload_module(void)
{
ast_mutex_lock(&odbc_lock);
if (connected) {
if (option_verbose > 10)
if (connected)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Disconnecting from %s\n", dsn);
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
SQLDisconnect(ODBC_con);
@@ -182,29 +203,38 @@ static int odbc_unload_module(void)
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
connected = 0;
}
if (dsn && dsn_alloc) {
if (option_verbose > 10)
if (dsn && dsn_alloc)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free dsn\n");
free(dsn);
dsn = NULL;
dsn_alloc = 0;
}
if (username && username_alloc) {
if (option_verbose > 10)
if (username && username_alloc)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free username\n");
free(username);
username = NULL;
username_alloc = 0;
}
if (password && password_alloc) {
if (option_verbose > 10)
if (password && password_alloc)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free password\n");
free(password);
password = NULL;
password_alloc = 0;
}
loguniqueid = 0;
if (loguniqueid && loguniqueid_alloc)
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free loguniqueid\n");
free(loguniqueid);
loguniqueid = NULL;
loguniqueid_alloc = 0;
}
ast_cdr_unregister(name);
ast_mutex_unlock(&odbc_lock);
return 0;
@@ -220,7 +250,8 @@ static int odbc_load_module(void)
ast_mutex_lock(&odbc_lock);
cfg = ast_load(config);
if (!cfg) {
if (!cfg)
{
ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config);
goto out;
}
@@ -232,85 +263,110 @@ static int odbc_load_module(void)
}
tmp = ast_variable_retrieve(cfg,"global","dsn");
if (tmp) {
if (tmp)
{
dsn = malloc(strlen(tmp) + 1);
if (dsn != NULL) {
memset(dsn, 0, strlen(tmp) + 1);
if (dsn != NULL)
{
dsn_alloc = 1;
strncpy(dsn, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
res = -1;
goto out;
strcpy(dsn,tmp);
}
} else {
else
{
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
return -1;
}
}
else
{
ast_log(LOG_WARNING,"cdr_odbc: dsn not specified. Assuming asteriskdb\n");
dsn = "asteriskdb";
}
tmp = ast_variable_retrieve(cfg,"global","username");
if (tmp) {
if (tmp)
{
username = malloc(strlen(tmp) + 1);
if (username != NULL) {
memset(username, 0, strlen(tmp) + 1);
if (username != NULL)
{
username_alloc = 1;
strncpy(username, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
res = -1;
goto out;
strcpy(username,tmp);
}
} else {
else
{
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
return -1;
}
}
else
{
ast_log(LOG_WARNING,"cdr_odbc: username not specified. Assuming root\n");
username = "root";
}
tmp = ast_variable_retrieve(cfg,"global","password");
if (tmp) {
if (tmp)
{
password = malloc(strlen(tmp) + 1);
if (password != NULL) {
memset(password, 0, strlen(tmp) + 1);
if (password != NULL)
{
password_alloc = 1;
strncpy(password, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
res = -1;
goto out;
strcpy(password,tmp);
}
} else {
else
{
ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
return -1;
}
}
else
{
ast_log(LOG_WARNING,"cdr_odbc: database password not specified. Assuming blank\n");
password = "";
}
tmp = ast_variable_retrieve(cfg,"global","loguniqueid");
if (tmp) {
loguniqueid = ast_true(tmp);
if (loguniqueid) {
if (tmp)
{
loguniqueid = malloc(strlen(tmp) + 1);
if (loguniqueid != NULL)
{
strcpy(loguniqueid,tmp);
loguniqueid_alloc = 1;
ast_log(LOG_NOTICE,"cdr_odbc: Logging uniqueid\n");
} else {
ast_log(LOG_ERROR,"cdr_odbc: Not logging uniqueid\n");
}
} else {
else
{
ast_log(LOG_ERROR,"cdr_odbc: Not logging uniqueid\n");
loguniqueid_alloc = 1;
loguniqueid = NULL;
}
}
else
{
ast_log(LOG_WARNING,"cdr_odbc: Not logging uniqueid\n");
loguniqueid = 0;
loguniqueid = NULL;
}
ast_destroy(cfg);
if (option_verbose > 2) {
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: dsn is %s\n",dsn);
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: username is %s\n",username);
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: password is [secret]\n");
if(option_verbose > 3)
{
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: dsn is %s\n",dsn);
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: username is %s\n",username);
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: password is [secret]\n");
}
res = odbc_init();
if (res < 0) {
if(res < 0)
{
ast_log(LOG_ERROR, "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
if (option_verbose > 2) {
ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
}
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
}
res = ast_cdr_register(name, desc, odbc_log);
if (res) {
if (res)
{
ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
}
out:
@@ -320,22 +376,25 @@ out:
static int odbc_do_query(void)
{
long int ODBC_err;
long int ODBC_err;
int ODBC_res;
short int ODBC_mlen;
char ODBC_msg[200], ODBC_stat[10];
short int ODBC_mlen;
char ODBC_msg[200], ODBC_stat[10];
ODBC_res = SQLExecute(ODBC_stmt);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
if (option_verbose > 10)
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in Query %d\n", ODBC_res);
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
connected = 0;
return -1;
} else {
if (option_verbose > 10)
}
else
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query Successful!\n");
connected = 1;
}
@@ -349,10 +408,13 @@ static int odbc_init(void)
int ODBC_res;
char ODBC_msg[200], ODBC_stat[10];
if (ODBC_env == SQL_NULL_HANDLE || connected == 0) {
if ( ODBC_env == SQL_NULL_HANDLE || connected == 0 )
{
ODBC_res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &ODBC_env);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
if (option_verbose > 10)
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHandle\n");
connected = 0;
return -1;
@@ -360,8 +422,9 @@ static int odbc_init(void)
ODBC_res = SQLSetEnvAttr(ODBC_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
if (option_verbose > 10)
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SetEnv\n");
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
connected = 0;
@@ -370,27 +433,32 @@ static int odbc_init(void)
ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
if (option_verbose > 10)
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHDB %d\n", ODBC_res);
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
connected = 0;
return -1;
}
SQLSetConnectAttr(ODBC_con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)10, 0);
}
ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
if (option_verbose > 10)
if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SQLConnect %d\n", ODBC_res);
SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
connected = 0;
return -1;
} else {
if (option_verbose > 10)
}
else
{
if(option_verbose > 3)
ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Connected to %s\n", dsn);
connected = 1;
}

View File

@@ -41,7 +41,7 @@ static char *pghostname = NULL, *pgdbname = NULL, *pgdbuser = NULL, *pgpassword
static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0, dbsock_alloc = 0, dbport_alloc = 0;
static int connected = 0;
AST_MUTEX_DEFINE_STATIC(pgsql_lock);
static ast_mutex_t pgsql_lock = AST_MUTEX_INITIALIZER;
PGconn *conn;
PGresult *result;
@@ -49,13 +49,19 @@ PGresult *result;
static int pgsql_log(struct ast_cdr *cdr)
{
struct tm tm;
char sqlcmd[2048] = "", timestr[128];
char *pgerror;
struct timeval tv;
char sqlcmd[2048], timestr[128];
time_t t;
char *pgerror;
ast_mutex_lock(&pgsql_lock);
localtime_r(&cdr->start.tv_sec,&tm);
strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
memset(sqlcmd,0,2048);
gettimeofday(&tv,NULL);
t = tv.tv_sec;
localtime_r(&t,&tm);
strftime(timestr,128,DATE_FORMAT,&tm);
if ((!connected) && pghostname && pgdbuser && pgpassword && pgdbname) {
conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword);
@@ -99,7 +105,7 @@ static int pgsql_log(struct ast_cdr *cdr)
ast_log(LOG_DEBUG,"cdr_pgsql: inserting a CDR record.\n");
snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s','%s')",timestr,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, uniqueid, userfield);
sprintf(sqlcmd,"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s','%s')",timestr,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, uniqueid, userfield);
ast_log(LOG_DEBUG,"cdr_pgsql: SQL command executed: %s\n",sqlcmd);
/* Test to be sure we're still connected... */
@@ -118,7 +124,6 @@ static int pgsql_log(struct ast_cdr *cdr)
ast_log(LOG_ERROR, "cdr_pgsql: Unable to reconnect to database server %s. Calls will not be logged!\n", pghostname);
ast_log(LOG_ERROR, "cdr_pgsql: Reason: %s\n", pgerror);
connected = 0;
ast_mutex_unlock(&pgsql_lock);
return -1;
}
}
@@ -127,19 +132,6 @@ static int pgsql_log(struct ast_cdr *cdr)
pgerror = PQresultErrorMessage(result);
ast_log(LOG_ERROR,"cdr_pgsql: Failed to insert call detail record into database!\n");
ast_log(LOG_ERROR,"cdr_pgsql: Reason: %s\n", pgerror);
ast_log(LOG_ERROR,"cdr_pgsql: Connection may have been lost... attempting to reconnect.\n");
PQreset(conn);
if (PQstatus(conn) == CONNECTION_OK) {
ast_log(LOG_ERROR, "cdr_pgsql: Connection reestablished.\n");
connected = 1;
result = PQexec(conn, sqlcmd);
if ( PQresultStatus(result) != PGRES_COMMAND_OK)
{
pgerror = PQresultErrorMessage(result);
ast_log(LOG_ERROR,"cdr_pgsql: HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n");
ast_log(LOG_ERROR,"cdr_pgsql: Reason: %s\n", pgerror);
}
}
ast_mutex_unlock(&pgsql_lock);
return -1;
}
@@ -155,9 +147,7 @@ char *description(void)
static int my_unload_module(void)
{
if (conn)
PQfinish(conn);
conn = NULL;
PQfinish(conn);
connected = 0;
if (pghostname && hostname_alloc) {
free(pghostname);
@@ -193,13 +183,20 @@ static int my_unload_module(void)
return 0;
}
static int process_my_load_module(struct ast_config *cfg)
static int my_load_module(void)
{
int res;
struct ast_config *cfg;
struct ast_variable *var;
char *pgerror;
char *tmp;
cfg = ast_load(config);
if (!cfg) {
ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
return 0;
}
var = ast_variable_browse(cfg, "global");
if (!var) {
/* nothing configured */
@@ -210,9 +207,8 @@ static int process_my_load_module(struct ast_config *cfg)
if (tmp) {
pghostname = malloc(strlen(tmp) + 1);
if (pghostname != NULL) {
memset(pghostname, 0, strlen(tmp) + 1);
hostname_alloc = 1;
strncpy(pghostname, tmp, strlen(tmp));
strcpy(pghostname,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
@@ -226,9 +222,8 @@ static int process_my_load_module(struct ast_config *cfg)
if (tmp) {
pgdbname = malloc(strlen(tmp) + 1);
if (pgdbname != NULL) {
memset(pgdbname, 0, strlen(tmp) + 1);
dbname_alloc = 1;
strncpy(pgdbname, tmp, strlen(tmp));
strcpy(pgdbname,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
@@ -242,9 +237,8 @@ static int process_my_load_module(struct ast_config *cfg)
if (tmp) {
pgdbuser = malloc(strlen(tmp) + 1);
if (pgdbuser != NULL) {
memset(pgdbuser, 0, strlen(tmp) + 1);
dbuser_alloc = 1;
strncpy(pgdbuser, tmp, strlen(tmp));
strcpy(pgdbuser,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
@@ -258,9 +252,8 @@ static int process_my_load_module(struct ast_config *cfg)
if (tmp) {
pgpassword = malloc(strlen(tmp) + 1);
if (pgpassword != NULL) {
memset(pgpassword, 0, strlen(tmp) + 1);
password_alloc = 1;
strncpy(pgpassword, tmp, strlen(tmp));
strcpy(pgpassword,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
@@ -274,9 +267,8 @@ static int process_my_load_module(struct ast_config *cfg)
if (tmp) {
pgdbport = malloc(strlen(tmp) + 1);
if (pgdbport != NULL) {
memset(pgdbport, 0, strlen(tmp) + 1);
dbport_alloc = 1;
strncpy(pgdbport, tmp, strlen(tmp));
strcpy(pgdbport,tmp);
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
@@ -286,6 +278,8 @@ static int process_my_load_module(struct ast_config *cfg)
pgdbport = "5432";
}
ast_destroy(cfg);
ast_log(LOG_DEBUG,"cdr_pgsql: got hostname of %s\n",pghostname);
ast_log(LOG_DEBUG,"cdr_pgsql: got port of %s\n",pgdbport);
if (pgdbsock)
@@ -300,7 +294,7 @@ static int process_my_load_module(struct ast_config *cfg)
connected = 1;
} else {
pgerror = PQerrorMessage(conn);
ast_log(LOG_ERROR, "cdr_pgsql: Unable to connect to database server %s. CALLS WILL NOT BE LOGGED!!\n", pghostname);
ast_log(LOG_ERROR, "cdr_pgsql: Unable to connect to database server %s. Calls will not be logged!\n", pghostname);
ast_log(LOG_ERROR, "cdr_pgsql: Reason: %s\n", pgerror);
connected = 0;
}
@@ -312,20 +306,6 @@ static int process_my_load_module(struct ast_config *cfg)
return res;
}
static int my_load_module(void)
{
struct ast_config *cfg;
int res;
cfg = ast_load(config);
if (!cfg) {
ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
return 0;
}
res = process_my_load_module(cfg);
ast_destroy(cfg);
return res;
}
int load_module(void)
{
return my_load_module();

Some files were not shown because too many files have changed in this diff Show More